Life Journey — Deployment Shell (Phase 0)
An empty, deployable shell for the async multiplayer board game. It contains no game logic yet — its only job is to prove the deployment path works: the server runs in Docker, is reachable through Nginx Proxy Manager over HTTPS, and WebSockets survive the reverse proxy.
Once both checks are green, adding the real game (Phase 1 onward) never touches the deployment story again.
What's here
lifegame/
├── docker-compose.yml
├── Dockerfile
├── package.json / package-lock.json
├── server/index.js # health endpoint + WebSocket echo
└── public/index.html # live HTTP + WebSocket status page
1. Put it on the homelab
Drop the folder in your services directory (e.g. ~/homelab/lifegame/) and build:
cd ~/homelab/lifegame
docker compose up -d --build
docker compose logs -f # expect: "Life Journey (Phase 0) listening on :3000"
Verify locally on the host first:
curl http://localhost:3000/api/health
# {"ok":true,"service":"life-journey","phase":0,...}
2. Point Nginx Proxy Manager at it
Add a Proxy Host:
- Domain: your chosen name, e.g.
game.example.com - Scheme:
http - Forward Hostname / IP:
- Option A (default compose): the homelab's LAN IP (e.g.
192.168.x.x) - Option B (shared network):
lifegame
- Option A (default compose): the homelab's LAN IP (e.g.
- Forward Port:
3000 - Websockets Support: ON ← the easy-to-forget one
- SSL tab: request a new Let's Encrypt certificate, Force SSL on
3. Confirm it works
Open https://game.example.com. You should see two rows go green:
- Server (HTTP) — the health endpoint responded
- WebSocket — a live socket connected through the proxy
Click Send WebSocket ping and the status should show the echo came back.
If HTTP is green but WebSocket is red, the proxy isn't upgrading the connection — go back and toggle Websockets Support on the proxy host.
Data & backups
The lifegame-data volume (mounted at /app/data) is where the SQLite
database and uploaded player tokens will live in later phases. It's empty now,
but include it in the same backup routine as your other self-hosted data.
What Phase 1 adds
- The shared
game.jsrules engine (the pure reducer from the prototype) - SQLite data model: games, players, board/rule config, tokens
- Rooms + shareable invite links / join codes
NetworkTransporton the client — the one-line swap that makes the game run across devices- Persistence & reconnection, since async means tabs close and servers restart