Production: Nginx + systemd
This guide shows a practical production workflow for running a Vix application on a Linux server with systemd and Nginx.
Use it when you want to run your app as a service, expose it behind a domain, enable HTTPS, check health, inspect logs, and deploy safely.
The goal
A typical production setup looks like this:
public internet
-> Nginx
-> Vix app on 127.0.0.1:<port>
-> systemd keeps the app runningFor WebSocket apps:
public internet
-> Nginx WebSocket location
-> Vix WebSocket server on 127.0.0.1:<ws_port>Vix gives you production commands for this workflow:
vix env check --production
vix service init
vix proxy nginx init
vix health
vix logs
vix deployBefore you start
This guide assumes:
Linux server
Git installed
Nginx installed
systemd available
Vix CLI installed
your app already builds with vix build
your app can run with vix runCheck the machine first:
vix doctor
vix infoRecommended production flow
Use this order:
vix env check --production
vix build --preset release
vix check --tests
vix service init
vix proxy nginx init
vix health
vix logsAfter the first setup, deployments can use:
vix deployProduction configuration in vix.json
A production app should describe service, proxy, health, logs, and deploy behavior in vix.json.
Example shape:
{
"production": {
"service": {
"name": "myapp",
"user": "www-data",
"working_dir": "/var/www/myapp",
"command": "vix run",
"env_file": "/var/www/myapp/.env"
},
"proxy": {
"domain": "api.example.com",
"http_port": 8080,
"websocket": {
"enabled": true,
"path": "/ws",
"port": 9090
},
"tls": {
"enabled": true,
"certificate": "/etc/letsencrypt/live/api.example.com/fullchain.pem",
"certificate_key": "/etc/letsencrypt/live/api.example.com/privkey.pem"
}
},
"health": {
"service": "myapp",
"local": "http://127.0.0.1:8080/health",
"public": "https://api.example.com/health",
"websocket": "wss://api.example.com/ws"
},
"logs": {
"service": "myapp",
"nginx_access": "/var/log/nginx/api.example.com.access.log",
"nginx_error": "/var/log/nginx/api.example.com.error.log"
},
"deploy": {
"pull": true,
"branch": "main",
"build": "vix build --preset release",
"tests": true,
"test_command": "vix check --tests",
"service": "myapp",
"health_local": true,
"health_public": true,
"proxy_check": true,
"proxy_reload": true,
"logs_on_failure": true,
"log_lines": 100,
"rollback": true
}
}
}Adjust names, paths, ports, and domain for your server.
Environment files
Use .env for runtime configuration:
SERVER_PORT=8080
VIX_LOG_LEVEL=info
VIX_LOG_FORMAT=kv
APP_ENV=productionFor production validation, define required variables in your production config or required env file.
Check local env:
vix env checkCheck production env:
vix env check --productionShow values safely:
vix env check --production --show-valuesSecrets stay masked.
Build before production
Before creating services or deploying, make sure the project builds:
vix build --preset releaseThen validate:
vix check --testsThis avoids creating a systemd service for an app that cannot build.
Create the systemd service
Use:
vix service initThis generates, installs, and enables a systemd service from your production config.
Then check it:
vix service statusRestart it:
vix service restartStop it:
vix service stopStart it:
vix service startThe service keeps your Vix app running after SSH disconnects and after server reboots.
Install the Nginx proxy
Use:
vix proxy nginx initThis generates and installs an Nginx site config.
It can configure:
HTTP reverse proxy
HTTPS redirect
TLS certificate paths
WebSocket upgrade location
proxy headers
timeouts
Nginx reloadCheck the proxy:
vix proxy nginx checkReload Nginx safely:
vix proxy nginx reloadIssue or renew certificates:
vix proxy nginx certbotPlain HTTP setup
For early testing, TLS can be disabled.
The proxy forwards:
http://your-domain/
-> http://127.0.0.1:8080/Useful for first server validation.
HTTPS setup
For real production, enable TLS.
The proxy should redirect HTTP to HTTPS:
http://api.example.com
-> https://api.example.comThen HTTPS forwards to the local app:
https://api.example.com
-> http://127.0.0.1:8080WebSocket setup
If WebSocket is enabled, Nginx must use upgrade headers.
Vix proxy handles this from config.
Example public WebSocket path:
wss://api.example.com/wsLocal upstream:
ws://127.0.0.1:9090/wsCheck it:
vix ws check
vix health websocketUse verbose mode when debugging:
vix ws check --verboseHealth checks
Use:
vix healthThis can check:
local application endpoint
public HTTPS endpoint
WebSocket endpointCheck only local:
vix health localCheck only public:
vix health publicCheck WebSocket:
vix health websocketRecommended after every deployment:
vix healthLogs
Read production logs with:
vix logsApp logs:
vix logs appProxy logs:
vix logs proxyErrors only:
vix logs errorsFollow logs:
vix logs app -fShow recent errors:
vix logs errors --lines 100Deployment
After service, proxy, health, and logs are configured, use:
vix deployA production deploy can:
pull latest code
build the project
run tests
restart systemd service
check local health
check public health
check proxy config
reload proxy
print logs on failure
rollback when enabledPreview without executing:
vix deploy --dry-runVerbose mode:
vix deploy --verboseSkip git pull:
vix deploy --no-pullSkip tests:
vix deploy --no-testsRecommended deployment flow
Use this before a serious deployment:
vix env check --production
vix deploy --dry-run
vix deploy --verbose
vix healthIf something fails:
vix logs errors --lines 100
vix service status
vix proxy nginx checkFirst-time server setup
A practical first setup:
git clone https://github.com/example/myapp.git
cd myapp
vix doctor
vix install
vix build --preset release
vix check --tests
cp .env.example .env
vix env check --production
vix service init
vix service status
vix proxy nginx init
vix proxy nginx check
vix healthNormal deployment workflow
After the first setup:
cd /var/www/myapp
vix deploy
vix healthIf you want to inspect before running:
vix deploy --dry-runDebugging production
Local health works, public health fails
Run:
vix health local
vix health public
vix proxy nginx check
vix logs proxy --lines 100This usually means the app is running, but proxy, TLS, DNS, firewall, or public routing needs attention.
Public HTTP works, WebSocket fails
Run:
vix health websocket
vix ws check --verbose
vix proxy nginx check
vix logs proxy --lines 100Check the WebSocket path and port.
Service does not start
Run:
vix service status
vix logs app --lines 100
vix env check --productionCommon causes:
missing env variables
wrong working directory
wrong command
missing executable
port already in use
permission issueDeployment failed
Run:
vix logs errors --lines 100
vix service status
vix healthThen inspect the step that failed in the deploy output.
Production safety rules
Do not deploy blindly.
Use:
vix deploy --dry-runbefore changing a server for the first time.
Do not delete global state before inspecting it.
Use:
vix infobefore cleanup.
Do not hardcode production ports in source code.
Prefer:
app.run();and configure the port in .env:
SERVER_PORT=8080Common mistakes
Running production commands before building
Correct flow:
vix build --preset release
vix check --tests
vix service initForgetting production env validation
Run:
vix env check --productionbefore deployment.
Checking only public health
Always check local first:
vix health local
vix health publicIf local fails, fix the app or service first.
If local passes and public fails, check Nginx, TLS, DNS, or firewall.
Forgetting WebSocket proxy config
If your app uses WebSocket, make sure it is enabled in production proxy config and test it:
vix ws check --verboseUsing vix clean for production cache problems
vix clean affects project-local state.
For global package store issues, inspect first:
vix info
vix store path
vix store gc --dry-runRecommended command map
| Need | Command |
|---|---|
| Check machine setup | vix doctor |
| Inspect Vix paths and caches | vix info |
| Check production env | vix env check --production |
| Build release | vix build --preset release |
| Validate project | vix check --tests |
| Create systemd service | vix service init |
| Check service | vix service status |
| Create Nginx proxy | vix proxy nginx init |
| Check Nginx proxy | vix proxy nginx check |
| Reload Nginx | vix proxy nginx reload |
| Check health | vix health |
| Check WebSocket | vix ws check |
| Read logs | vix logs |
| Deploy | vix deploy |
Related commands
| Command | Purpose |
|---|---|
vix service | Manage systemd service |
vix proxy | Manage Nginx reverse proxy |
vix health | Check local, public, and WebSocket endpoints |
vix logs | Read app, proxy, and error logs |
vix env | Validate local and production environment files |
vix deploy | Run production deployment workflow |
vix ws | Check WebSocket endpoint |
vix doctor | Diagnose server environment |
vix info | Inspect Vix local state |
What you should remember
A production Vix app should be observable and easy to recover.
The stable workflow is:
vix env check --production
vix build --preset release
vix check --tests
vix service init
vix proxy nginx init
vix healthThen deploy with:
vix deployAnd debug with:
vix health
vix logs errors --lines 100
vix service status
vix proxy nginx checkNext step
Return to the guides overview.