┌──────────────────────────────────────────────────────────────┐
│ Hetzner VPS (5.161.250.43) │
│ │
│ bobsgame.com ws.bobsgame.com │
│ ├─ nginx (SSL) ├─ nginx (SSL, reverse proxy) │
│ ├─ /var/www/ ├─ proxy_pass localhost:6065 │
│ │ bobsgame.com/ ├─ /opt/bobsgameweb/server/ │
│ │ current/ │ ├─ index.js (Socket.io + Express) │
│ │ ├─ index.html │ └─ systemd: bobsgameweb-server │
│ │ └─ assets/ │ │
│ └─ Let's Encrypt SSL └─ Let's Encrypt SSL │
└──────────────────────────────────────────────────────────────┘
- SSH access to Hetzner VPS (
root@5.161.250.43) - SSH access to backend host (
root@ws.bobsgame.com) sshpassinstalled (or SSH key configured)- Node.js 18+ on the VPS for the backend
- nginx and certbot installed on the VPS
cd bobsgameweb
# Bump version first!
FRONTEND_HOST=5.161.250.43 FRONTEND_USER=root bash scripts/deploy-frontend-hetzner.shcd bobsgameweb
BACKEND_HOST=ws.bobsgame.com BACKEND_FORCE_TAR=1 BACKEND_RESTART=1 bash scripts/deploy-backend-vps.shIMPORTANT: Always use BACKEND_FORCE_TAR=1 — rsync fails on Windows/Cygwin.
cd bobsgameweb
npx vite build # DO NOT use "npm run build" — git paging file error on WindowsUpdate version in these 4 files:
VERSION.md— just the version stringpackage.json—"version"fieldsrc/renderer/scenes/MainMenuScene.ts— displayed in main menuserver/index.js— reported by/healthz
npx tsc --noEmit # Should show 0 errors (2 pre-existing NDDemoScene errors are ok)
ls dist/renderer/ # Should have index.html + assets/FRONTEND_HOST=5.161.250.43 FRONTEND_USER=root bash scripts/deploy-frontend-hetzner.shThis uploads dist/ contents to /var/www/bobsgame.com/current/ via scp.
BACKEND_HOST=ws.bobsgame.com BACKEND_FORCE_TAR=1 BACKEND_RESTART=1 bash scripts/deploy-backend-vps.shThis uploads server/ via tar-over-SSH and restarts the systemd service.
# Backend health check
curl -s https://ws.bobsgame.com/healthz
# Expected: {"ok":true,"service":"bobsgameweb-socket-server","version":"2.1.XX",...}
# Frontend check
curl -sI https://bobsgame.com/ | head -1
# Expected: HTTP/1.1 200 OK
# Socket.io check
curl -s "https://ws.bobsgame.com/socket.io/?EIO=4&transport=polling"
# Expected: 0{"upgrades":["websocket"],...}cd bobsgameweb
git add -A
git commit -m "v2.1.XX: description of changes"
git push origin master- Format:
MAJOR.MINOR.PATCH(e.g.,2.1.73) - Bump PATCH for each deploy during a session
- Bump MINOR for new features/subsystems
- Bump MAJOR for breaking changes
- Always reference the version in the commit message
# Check status
systemctl status bobsgameweb-server
# View logs
journalctl -u bobsgameweb-server -f
# Restart
systemctl restart bobsgameweb-server
# Stop/Start
systemctl stop bobsgameweb-server
systemctl start bobsgameweb-serverFrontend: /etc/nginx/sites-available/bobsgame.com
- Serves static files from
/var/www/bobsgame.com/current - SPA fallback (try_files $uri /index.html)
- SSL via Let's Encrypt
Backend: /etc/nginx/sites-available/ws.bobsgame.com
- Reverse proxy to
localhost:6065 - WebSocket upgrade headers for Socket.io
- SSL via Let's Encrypt
→ Use npx vite build instead of npm run build
→ Use BACKEND_FORCE_TAR=1 environment variable
→ Check systemd status: systemctl status bobsgameweb-server
→ Check nginx: nginx -t
→ Check logs: journalctl -u bobsgameweb-server -n 50
→ Check files exist: ls /var/www/bobsgame.com/current/
→ Check nginx config: nginx -t
→ Remove stale lock: rm -f .git/index.lock
→ DO NOT remove while git operations are running
cd okgame/build
cmake .. && makecd bobsgameonlinejava
./gradlew desktop:dist --no-daemon