Production: Nginx + systemd
This guide shows how to deploy a Vix application in production behind Nginx and systemd.
Final architecture
txt
browser → HTTPS → Nginx → reverse proxy → Vix app → systemd serviceProduction goal
txt
Vix listens on localhost:8080
Nginx handles public HTTP/HTTPS
systemd keeps the app running
Certbot manages TLS certificatesBuild the app
bash
cd /home/vix/apps/myapp
vix build --preset release
# With SQLite: vix build --preset release --with-sqlite
# With MySQL: vix build --preset release --with-mysqlTest locally before systemd
bash
./build-release/myapp
curl -i http://127.0.0.1:8080/healthUse .env
dotenv
SERVER_PORT=8080
SERVER_TLS_ENABLED=false
VIX_LOG_LEVEL=info
VIX_LOG_FORMAT=kv
VIX_COLOR=neverWhen Nginx handles HTTPS, your Vix app runs plain HTTP locally.
Create a systemd service
bash
sudo nano /etc/systemd/system/vix-myapp.serviceini
[Unit]
Description=Vix MyApp service
After=network.target
[Service]
Type=simple
User=vix
Group=vix
WorkingDirectory=/home/vix/apps/myapp
ExecStart=/home/vix/apps/myapp/build-release/myapp
Restart=always
RestartSec=3
Environment=VIX_LOG_LEVEL=info
Environment=VIX_LOG_FORMAT=kv
Environment=VIX_COLOR=never
LimitNOFILE=65535
[Install]
WantedBy=multi-user.targetbash
sudo systemctl daemon-reload
sudo systemctl enable vix-myapp
sudo systemctl start vix-myapp
sudo systemctl status vix-myappCheck logs
bash
journalctl -u vix-myapp -f
journalctl -u vix-myapp -n 100Restart after deployment
bash
sudo systemctl restart vix-myapp
curl -i http://127.0.0.1:8080/healthNginx reverse proxy
bash
sudo nano /etc/nginx/sites-available/myappnginx
server {
listen 80;
server_name example.com www.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}bash
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo nginx -t
sudo systemctl reload nginxNginx for WebSocket
nginx
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";Enable HTTPS with Certbot
bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-runHTTPS Nginx config shape
nginx
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}Firewall
bash
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enableUseful commands
bash
# systemd
sudo systemctl start|stop|restart|status vix-myapp
sudo systemctl enable|disable vix-myapp
journalctl -u vix-myapp -f
# Nginx
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginxDeployment flow
bash
cd /home/vix/apps/myapp
git pull origin main
vix build --preset release
sudo systemctl restart vix-myapp
curl -i http://127.0.0.1:8080/health
curl -i https://example.com/healthCommon production errors
502 Bad Gateway
App is not running. Check: sudo systemctl status vix-myapp and curl -i http://127.0.0.1:8080/health.
504 Gateway Timeout
Slow database query or overloaded VPS. Check logs.
WebSocket closes immediately
Add Nginx upgrade headers and longer timeouts:
nginx
proxy_read_timeout 3600;
proxy_send_timeout 3600;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";Security checklist
- HTTPS enabled
- Vix app not exposed directly to public internet
- Nginx forwards real client headers
.envis not public and has safe permissions (chmod 600)- Service runs as non-root user
- Firewall allows only SSH and Nginx
- Login routes have rate limiting
- CORS allows only trusted origins
Deployment checklist
- Build succeeds locally
- Binary runs manually on server
/healthworks locally- systemd service starts
- Nginx config passes
nginx -t - Domain points to server
- HTTPS certificate is installed
/healthworks through public domain- Logs are visible
- Restart flow is documented