The target architecture
Node.js listens on a local port (3000), Nginx serves HTTPS at the front and reverse-proxies to Node, PM2 keeps the process alive. This is the most proven architecture for a single VPS.
Step 1 — Node.js 22 LTS
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejsStep 2 — Deploy the application
Clone your repository into /var/www/myapp, install dependencies in production mode (npm ci --omit=dev), and create a dedicated user owning the folder.
Step 3 — PM2 in production
npm install -g pm2
pm2 start dist/server.js --name myapp --max-memory-restart 500M
pm2 startup systemd -u deploy --hp /home/deploy
pm2 save--max-memory-restart cleanly restarts the app on memory leaks — essential over a long run.
Step 4 — Nginx as reverse proxy
server {
listen 443 ssl http2;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Step 5 — HTTPS with Let's Encrypt
apt install certbot python3-certbot-nginx && certbot --nginx -d api.example.com. Renewal is automatic.
Step 6 — Zero downtime
pm2 reload myapp reloads workers without cutting connections. For Git deployments: a simple git pull && npm ci && pm2 reload in a script or GitHub Action is enough at VPS scale.
Environment variables
Never put secrets in the repository: a chmod 600 .env file, loaded by PM2 via ecosystem.config.js. On our platform, the VPS is yours — nobody else reads that file.