Files
i-want-to-heal/DEPLOYMENT.md
T
Warren H 3a8d5ad8c5 changes
2026-06-18 22:28:04 -04:00

4.1 KiB

Self-Hosting

The game can run on your own Windows PC and use router port forwarding. Account registration, sessions, characters, progression, inventory, loot history, and leaderboards are stored in the SQLite database at data/game.db.

That database file is the persistent storage. It remains after the server or PC restarts. If the file is deleted or lost, all accounts and save data are lost, so keep regular backups.

Build and run

npm ci
npm run db:init
npm run build
$env:HOST = "127.0.0.1"
$env:PORT = "4173"
$env:TRUST_PROXY = "1"
npm start

Run npm run db:init after pulling schema changes. It creates missing tables and seed content without erasing existing player data.

Internet access

Do not expose the Node port directly over unencrypted HTTP. Passwords would travel across the internet without encryption. Put Caddy or another HTTPS reverse proxy in front of the game:

game.example.com {
  reverse_proxy 127.0.0.1:4173
}

Point a domain or dynamic-DNS name to your public IP, forward router ports 80 and 443 to the PC running Caddy, and allow those ports through Windows Firewall. Caddy obtains and renews the HTTPS certificate.

Keep the game server bound to 127.0.0.1. Set TRUST_PROXY=1 only when the server can be reached solely through your local reverse proxy. This lets account limits use the visitor's public IP instead of the proxy's address.

Separate auth server

The auth routes can run as their own Node process. This is useful when you want auth.phenomrom.com to stay available while the game server is being rebuilt or changed.

On the TrueNAS host, run the auth process against the same project data folder:

npm ci
npm run db:init
AUTH_HOST=127.0.0.1 AUTH_PORT=4174 TRUST_PROXY=1 COOKIE_SECURE=1 AUTH_CORS_ORIGINS=https://phenomrom.com npm run auth:start

Point auth.phenomrom.com at that process through HTTPS:

auth.phenomrom.com {
  reverse_proxy 127.0.0.1:4174
}

Build the web or mobile app with the auth base URL set separately from the game API:

VITE_AUTH_API_BASE_URL=https://auth.phenomrom.com npm run build

For a Capacitor wrapper, set window.CAPACITOR_AUTH_API_BASE_URL to https://auth.phenomrom.com the same way window.CAPACITOR_API_BASE_URL is set. The app stores the returned bearer token locally and sends it with later API requests, so auth works across subdomains and inside the mobile WebView. Existing same-origin cookie sessions still work when auth is served by the game server.

Account limits

Registration permits one account per public IP by default. Login and API rate limits also apply. To allow a shared household to create more accounts, run a local administrator command:

npm run accounts:ip -- set 203.0.113.42 4 Smith-household
npm run accounts:ip -- list
npm run accounts:ip -- remove 203.0.113.42

set changes the total number of accounts that address may create. remove returns it to the default one-account limit. These commands must be run on the host PC and are not exposed through the website.

An IP account limit reduces casual account spam, but it is not DDoS protection. Your router and internet connection can still be overwhelmed before requests reach the game. Keep Windows patched, expose only required ports, and use router or ISP protections where available.

Backups

Create a consistent live backup with:

npm run db:backup

Backups are written to backups/game-<timestamp>.db. Copy them to another disk or cloud backup location; backups left only on the game PC will not help if its drive fails. Test restoration occasionally by stopping the server, preserving the current data/game.db, and placing a backup at that path.

Current scaling boundary

SQLite is a good fit for a small private server running one game process. Do not run multiple Node server instances against this setup.

Combat currently runs in the browser. It is suitable for a friend group, but a modified client could submit false completion metrics. Move combat simulation and run validation to the server before treating rankings as cheat-resistant.