This document is provider-neutral and applies whether the Node/Socket.io backend is hosted on a VPS, Hetzner, DigitalOcean, Railway, Render, or a DreamHost subdomain with proper Node support.
- Node 20+ preferred
- persistent process support
- websocket support
- ability to set environment variables
- reverse proxy or provider support for websocket upgrades
HOST=0.0.0.0
PORT=6065
ALLOWED_ORIGIN=https://bobsgame.comIf using a dedicated backend domain like ws.bobsgame.com, set:
ALLOWED_ORIGIN=https://bobsgame.comcd server
npm install
node index.jscd server
node app.jscd server
npm install -g pm2
pm2 start ecosystem.config.cjs
pm2 saveFor VPS/systemd deployments, a separate env file path is now supported via the unit file:
/etc/bobsgameweb-server.envUse the helper script:
BACKEND_HOST=YOUR-BACKEND-HOST BACKEND_USER=root ENV_ALLOWED_ORIGIN=https://bobsgame.com ./scripts/install-backend-env.shcd server
docker build -t bobsgameweb-server .
docker run -p 6065:6065 -e HOST=0.0.0.0 -e PORT=6065 -e ALLOWED_ORIGIN=https://bobsgame.com bobsgameweb-serverVerify these before touching the frontend config:
curl -i https://YOUR-BACKEND-HOST/
curl -i https://YOUR-BACKEND-HOST/healthz
curl -i "https://YOUR-BACKEND-HOST/socket.io/?EIO=4&transport=polling"For drift-aware verification on Hetzner/VPS installs, also run:
BACKEND_HOST=YOUR_SERVER_IP BACKEND_URL=https://YOUR-BACKEND-HOST ./scripts/audit-backend-drift.shThis compares:
- local tracked backend source
- remote backend files on disk
- live running backend process version from
/healthz
For version-aware backend health checks, you can also use:
BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.48 ./scripts/check-backend-host.shIf a no-restart maintenance window intentionally leaves runtime drift in place, use:
BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.52 ALLOW_BACKEND_RUNTIME_DRIFT=1 ./scripts/check-backend-host.shWhen a real restart window becomes available, capture a readiness snapshot first:
BACKEND_HOST=YOUR_SERVER_IP BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.52 ./scripts/snapshot-backend-restart-readiness.shThen prepare with the dry-run maintenance helper:
BACKEND_HOST=YOUR_SERVER_IP BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.52 ./scripts/run-backend-maintenance-restart.shAfter the restart window, compare the current state against the saved snapshot:
SNAPSHOT_FILE=artifacts/pre-restart.txt BACKEND_HOST=YOUR_SERVER_IP BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.52 ./scripts/compare-backend-restart-snapshot.shAnd only execute the restart when explicitly allowed:
BACKEND_HOST=YOUR_SERVER_IP BACKEND_URL=https://YOUR-BACKEND-HOST EXPECTED_BACKEND_VERSION=2.1.52 EXECUTE_BACKEND_RESTART=1 ./scripts/run-backend-maintenance-restart.shFor the full ordered operator procedure, including success criteria for each phase, see MAINTENANCE_WINDOW_RUNBOOK.md.
Expected:
/→ 200 plain text/healthz→ 200 JSON withok: true/socket.io/...→ Socket.io response, not provider 404
Once the backend host works, you can use the helper scripts:
BACKEND_URL=https://YOUR-BACKEND-HOST ./scripts/check-backend-host.sh
BACKEND_URL=https://YOUR-BACKEND-HOST ./scripts/rebuild-for-backend.shTo rebuild and immediately redeploy static assets:
BACKEND_URL=https://YOUR-BACKEND-HOST DEPLOY_STATIC=1 DEPLOY_HOST=dreamhost-bobsgame ./scripts/rebuild-for-backend.shOr use the combined cutover helper:
BACKEND_URL=https://YOUR-BACKEND-HOST DEPLOY_STATIC=1 DEPLOY_HOST=dreamhost-bobsgame ./scripts/cutover-production.shIf you need to align backend files on disk without restarting the live service:
BACKEND_HOST=YOUR_SERVER_IP BACKEND_USER=root BACKEND_FORCE_TAR=1 BACKEND_RESTART=0 ./scripts/deploy-backend-vps.shThis is useful when:
- you must not kill/restart processes right now
- you still want
/opt/bobsgameweb/serverto match tracked source - you want the next planned restart to pick up already-synced code
- run
node index.jsor PM2/systemd - bind backend to localhost or
0.0.0.0 - put nginx/Caddy in front
- terminate TLS at the proxy
- for Hetzner specifically, see
HETZNER_SETUP.mdplus:server/ops/nginx/ws.bobsgame.com.confserver/ops/nginx/ws.bobsgame.com.ssl.confserver/ops/systemd/bobsgameweb-server.serviceserver/ops/bootstrap-ubuntu.shserver/ops/cloud-init/hetzner-user-data.yamlscripts/deploy-backend-vps.shscripts/install-backend-env.shscripts/install-backend-service.shscripts/collect-backend-diagnostics.shscripts/provision-hetzner-backend.shscripts/cutover-production.shHARDENING_CHECKLIST.md
- set
HOST,PORT, andALLOWED_ORIGIN - use the platform port assignment
- verify
/healthzbefore rebuilding the frontend
- use
app.jsas startup entrypoint - verify
GET /healthzworks before testing Socket.io - if Passenger/Node app hosting is unavailable, use a VPS or external backend host instead