Production deployment
In the previous chapter, you learned P2P. Now you will learn how to deploy a Vix application in production.
browser
-> HTTPS
-> Nginx
-> Vix app on localhost
-> systemdWhy production deployment matters
During development, you usually run:
vix devProduction is different.
A production application needs:
- A release build
- A stable working directory
- A systemd service
- Environment validation
- Logs
- A reverse proxy
- HTTPS
- Health checks
- WebSocket checks when needed
- A safe deployment workflow
Vix now provides commands for these production tasks.
Instead of manually writing everything from scratch every time, the production workflow becomes:
vix env check --production
vix build --preset release
vix check --tests
vix service init
vix proxy nginx init
vix health
vix logs
vix deployProduction architecture
A normal Vix production setup looks like this:
Internet
-> Nginx
-> 127.0.0.1:8080
-> Vix app
-> systemdNginx handles public HTTP and HTTPS.
The Vix app listens locally.
systemd keeps the app alive.
For WebSocket apps:
Internet
-> Nginx WebSocket location
-> 127.0.0.1:9090
-> Vix WebSocket serverDevelopment vs production
| Development | Production |
|---|---|
vix dev | vix service |
| Hot reload | Stable systemd process |
| Terminal logs | vix logs |
| Local browser | Nginx reverse proxy |
| Manual restart | systemd restart policy |
| Local env | production env validation |
| Manual checks | vix health |
| Manual deployment | vix deploy |
The important idea is simple:
development optimizes iteration
production optimizes stabilityThe production command set
Vix includes production-oriented commands:
| Command | Purpose |
|---|---|
vix env check --production | Validate production environment configuration |
vix service | Manage the systemd service |
vix proxy nginx | Generate, check, reload, and configure Nginx |
vix health | Check local, public, and WebSocket endpoints |
vix logs | Read app, proxy, and error logs |
vix ws check | Check WebSocket endpoint behavior |
vix deploy | Run the deployment workflow |
These commands make production less manual and more predictable.
Production configuration
Production behavior should be described in vix.json.
Example:
{
"production": {
"service": {
"name": "myapp",
"user": "vix",
"working_dir": "/home/vix/apps/myapp",
"command": "vix run",
"env_file": "/home/vix/apps/myapp/.env"
},
"proxy": {
"domain": "example.com",
"http_port": 8080,
"websocket": {
"enabled": true,
"path": "/ws",
"port": 9090
},
"tls": {
"enabled": true,
"certificate": "/etc/letsencrypt/live/example.com/fullchain.pem",
"certificate_key": "/etc/letsencrypt/live/example.com/privkey.pem"
}
},
"health": {
"service": "myapp",
"local": "http://127.0.0.1:8080/health",
"public": "https://example.com/health",
"websocket": "wss://example.com/ws"
},
"logs": {
"service": "myapp",
"nginx_access": "/var/log/nginx/example.com.access.log",
"nginx_error": "/var/log/nginx/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
}
}
}This config gives Vix enough information to manage the service, proxy, logs, health checks, and deployments.
Prepare the server
Install the required system packages:
sudo apt update
sudo apt install -y \
build-essential cmake ninja-build pkg-config \
git nginx certbot python3-certbot-nginxDepending on your app, you may also need:
sudo apt install -y \
libssl-dev libsqlite3-dev zlib1g-dev libbrotli-dev \
nlohmann-json3-dev libspdlog-dev libfmt-devThen check the machine:
vix doctor
vix infoUse vix doctor to diagnose tools and environment readiness.
Use vix info to inspect Vix paths, registry state, store state, global packages, and artifact cache state.
Create a production user
A production app should not run as root.
Create a dedicated user:
sudo useradd --system --create-home --shell /usr/sbin/nologin vix
sudo mkdir -p /home/vix/apps/myapp
sudo chown -R vix:vix /home/vix/appsClone your project:
sudo -u vix git clone https://github.com/example/myapp.git /home/vix/apps/myapp
cd /home/vix/apps/myappConfigure environment
Create .env:
sudo -u vix nano /home/vix/apps/myapp/.envExample:
SERVER_HOST=127.0.0.1
SERVER_PORT=8080
SERVER_TLS_ENABLED=false
VIX_LOG_LEVEL=info
VIX_LOG_FORMAT=kv
VIX_COLOR=never
APP_ENV=productionWhen Nginx handles HTTPS, keep the Vix app local and plain HTTP:
SERVER_TLS_ENABLED=falseNginx terminates TLS and proxies to the local Vix process.
Validate environment
Before building or deploying:
vix env check --productionTo show values safely:
vix env check --production --show-valuesSecrets are always masked.
Use this command when:
.env may be missing
.env.example may be incomplete
required production variables may be missing
systemd environment may not match project expectationsInstall dependencies
If your project uses the registry:
vix registry sync
vix installUse vix install, not the old vix deps wording.
vix install installs exact locked dependencies from vix.lock.
Build a release version
Build the app:
vix build --preset releaseValidate it:
vix check --testsIf the app uses SQLite or MySQL support, use the build options supported by your project:
vix build --preset release --with-sqlite
vix build --preset release --with-mysqlThe exact flags depend on the project configuration.
Test locally before service setup
Before creating the service, test the app manually:
vix runThen check the local health endpoint:
curl -i http://127.0.0.1:8080/healthStop the app with Ctrl+C.
Create the systemd service
Use:
vix service initThis uses your production config to generate, install, and enable a systemd service.
Then check service state:
vix service statusRestart when needed:
vix service restartStop:
vix service stopStart:
vix service startThe service keeps the app running after SSH disconnects and after server restarts.
Install the Nginx proxy
Use:
vix proxy nginx initThis generates and installs the 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 a certificate:
vix proxy nginx certbotPlain HTTP setup
For first server testing, TLS can be disabled.
The proxy forwards:
http://example.com/
-> http://127.0.0.1:8080/This is useful before enabling HTTPS.
HTTPS setup
For real production, enable TLS.
The proxy should redirect HTTP to HTTPS:
http://example.com
-> https://example.comThen HTTPS forwards to the local app:
https://example.com
-> http://127.0.0.1:8080Vix proxy can use certificate paths from your production config.
WebSocket setup
If the app uses WebSocket, enable the WebSocket proxy section.
Example public URL:
wss://example.com/wsLocal upstream:
ws://127.0.0.1:9090/wsCheck it:
vix health websocket
vix ws checkUse verbose mode when debugging:
vix ws check --verboseHealth checks
Check everything:
vix healthCheck only the local app:
vix health localCheck the public endpoint:
vix health publicCheck WebSocket:
vix health websocketA good health route returns a simple response:
{
"ok": true,
"service": "myapp"
}A more detailed production health response can include:
{
"ok": true,
"service": "myapp",
"database": "ok",
"sync": "enabled"
}Logs
Read all configured logs:
vix logsApp logs:
vix logs appProxy logs:
vix logs proxyErrors only:
vix logs errorsFollow logs:
vix logs app -fShow the last 100 error lines:
vix logs errors --lines 100Use logs immediately after a failed deploy:
vix logs errors --lines 100Deployment
After the first setup, use:
vix deployA deploy can:
pull latest code
build the app
run tests
restart the systemd service
check local health
check public health
check proxy config
reload proxy
print logs on failure
rollback when enabledPreview the deployment without executing:
vix deploy --dry-runRun with more details:
vix deploy --verboseSkip git pull:
vix deploy --no-pullSkip tests:
vix deploy --no-testsRecommended first production setup
Use this flow on a new server:
cd /home/vix/apps/myapp
vix doctor
vix info
vix registry sync
vix install
vix env check --production
vix build --preset release
vix check --tests
vix service init
vix service status
vix proxy nginx init
vix proxy nginx check
vix health
vix logsThis gives you a working production baseline.
Recommended deployment flow
After the first setup:
cd /home/vix/apps/myapp
vix env check --production
vix deploy --dry-run
vix deploy --verbose
vix healthFor normal deploys:
vix deploy
vix healthDebugging 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 Nginx, 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, upstream port, and proxy upgrade headers.
Service does not start
Run:
vix service status
vix logs app --lines 100
vix env check --productionCommon causes:
missing environment variables
wrong working directory
wrong command
missing binary
port already in use
permission problemDeployment failed
Run:
vix logs errors --lines 100
vix service status
vix healthThen inspect which deploy step failed.
Database production notes
For SQLite:
DATABASE_ENGINE=sqlite
DATABASE_DEFAULT_NAME=/home/vix/apps/myapp/data/app.dbCheck database state:
vix db statusRun migrations:
vix db migrateCreate a backup:
vix db backupFor ORM workflows:
vix orm status --db myapp --dir ./migrations
vix orm migrate --db myapp --dir ./migrationsFor MySQL, create a dedicated database user:
CREATE DATABASE myapp;
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'change-me';
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO 'myapp'@'localhost';
FLUSH PRIVILEGES;Firewall
Allow SSH, HTTP, and HTTPS:
sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw enableDo not expose the local app port publicly unless you explicitly need it.
The app should usually listen on:
127.0.0.1:8080not:
0.0.0.0:8080when it is behind Nginx.
Common production errors
502 Bad Gateway
Nginx cannot reach the Vix app.
Check:
vix service status
vix health local
vix logs app --lines 100504 Gateway Timeout
The app accepted the connection but did not respond fast enough.
Check:
vix logs app --lines 100
vix health localPossible causes:
slow database query
blocked request
overloaded VPS
bad upstream timeoutWebSocket closes immediately
Check:
vix ws check --verbose
vix proxy nginx check
vix logs proxy --lines 100Possible causes:
wrong WebSocket path
wrong upstream port
missing upgrade headers
timeout too shortApp works locally but not through the domain
Check:
vix health local
vix health public
vix proxy nginx checkThen check DNS, firewall, TLS, and Nginx logs.
Common mistakes
Running production manually forever
Manual run:
vix runProduction run:
vix service init
vix service statusProduction should be managed by systemd.
Running the app as root
Use a dedicated user.
Example:
vixnot:
rootForgetting the working directory
Relative paths depend on the service working directory.
Examples:
.env
public/
data/
storage/If the working directory is wrong, the app may start but fail to find files.
Debug logging forever
Use this for debugging:
VIX_LOG_LEVEL=debugUse this for normal production:
VIX_LOG_LEVEL=infoExposing internal routes
Protect admin, P2P control, deploy, and internal diagnostic routes.
Routes like this should not be public without authentication:
POST /p2p/connect
POST /admin/*
POST /internal/*Deploying without health checks
Always check after deploy:
vix healthProduction checklist
- [ ] Server has required build tools
- [ ] Vix CLI works
- [ ]
vix doctorpasses enough checks - [ ] Project dependencies are installed with
vix install - [ ]
.envexists - [ ]
vix env check --productionpasses - [ ] Release build works
- [ ] Tests pass
- [ ] App listens on localhost
- [ ] Health route works locally
- [ ] systemd service starts
- [ ] Logs are visible
- [ ] Nginx proxy is installed
- [ ]
vix proxy nginx checkpasses - [ ] Domain points to server
- [ ] HTTPS works
- [ ] WebSocket works if needed
- [ ]
vix healthpasses - [ ]
vix deploy --dry-runlooks correct - [ ]
vix deployworks
Recommended production structure
/home/vix/apps/myapp/
├── build-release/
├── data/
├── public/
├── src/
├── .env
├── vix.json
└── vix.lock
/etc/systemd/system/myapp.service
/etc/nginx/sites-available/myapp
/etc/nginx/sites-enabled/myappWhat you should remember
A Vix production app is a normal native Linux service, but Vix gives you commands to manage the full workflow.
browser
-> HTTPS
-> Nginx
-> Vix app on localhost
-> systemdFirst setup:
vix env check --production
vix build --preset release
vix check --tests
vix service init
vix proxy nginx init
vix healthNormal deploy:
vix deploy
vix healthDebugging:
vix health
vix logs errors --lines 100
vix service status
vix proxy nginx checkThe core idea is:
Vix should not only build the app.
Vix should help you run, expose, check, log, and deploy it safely.