Self-hosting with pm2 and nginx

On a Linux VM

A single VM (GCP Compute Engine, AWS EC2, DigitalOcean) is cheap and simple. pm2 keeps the Node process running and restarts it on crashes or reboots; nginx handles HTTPS and forwards to port 3000.

Example

git pull && npm ci && npm run build
pm2 start npm --name shopease-web -- start
pm2 save && pm2 startup

Example output

[PM2] Starting /usr/bin/npm in fork_mode (1 instance)
[PM2] Done.
┌────┬──────────────┬─────────┬──────┬────────┬──────────┐
│ id │ name         │ mode    │ ↺    │ status │ memory   │
├────┼──────────────┼─────────┼──────┼────────┼──────────┤
│ 0  │ shopease-web │ fork    │ 0    │ online │ 142.6mb  │
└────┴──────────────┴─────────┴──────┴────────┴──────────┘

nginx Reverse Proxy

nginx site

/etc/nginx/sites-available/shopease

server {
    server_name shopease.in www.shopease.in;

    location /_next/static/ {
        proxy_pass http://127.0.0.1:3000;
        add_header Cache-Control "public, max-age=31536000, immutable";
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;              # keep streaming working
    }

    listen 443 ssl;                       # managed by Certbot
}

Example

sudo nginx -t && sudo systemctl reload nginx && sudo certbot --nginx -d shopease.in

Example output

nginx: configuration file /etc/nginx/nginx.conf test is successful
Successfully deployed certificate for shopease.in

Self-hosting Notes

  • ISR and the data cache are stored on the local disk. With several instances, configure a shared cacheHandler (e.g. Redis) so they agree.
  • Image optimisation needs sharp (installed automatically in recent versions).
  • Zero-downtime deploys: build into a new folder, then pm2 reload, or run two containers behind nginx.