Hosting and recovery¶
Live and verified on 11 September 2026: fightthefrontier.com. The game, live map and wiki share this address. www redirects to it. The dedicated Sydney server continues running with Alex's Mac game supervisor and Cloudflare tunnel stopped and disabled.
Server and cost¶
The dedicated DigitalOcean project is Fight the Frontier, using the approved existing My Team account and PayPal billing. The server is fight-the-frontier-syd1, Droplet 599628822: Sydney (syd1), s-1vcpu-1gb, 1 shared vCPU, 1 GiB RAM, 25 GiB SSD and 1,000 GiB monthly outbound transfer. No unrelated hosting or payment configuration was changed.
The approved cost is US$6/month plus US$1.80 for daily backups: US$7.80/month before tax. Extra transfer is US$0.01/GiB; domain renewal is separate. There is no additional managed database, paid registry, load balancer or storage volume. VM pricing, backup pricing, transfer pricing.
Cloudflare holds two DNS-only records: the apex A record points to this VM and www aliases the apex. Caddy supplies renewable HTTPS certificates and secure WebSockets. Port 8090 and SQLite stay private. Key-only SSH is restricted to the administrator's approved address; changing networks may require updating that firewall rule through DigitalOcean. No provider token is stored in the game image.
What passed¶
- A verified Linux runtime was deployed with the Reedwatch lighting fix from source commit
3cbe9c5111bb63ef440f19e65f410341cc966e7d. The staff stays upright outside the brazier's bars, with embers arcing over the rim. Shared hand attachment, approach clearance and cancellation checks passed, and both player views were inspected with the actual character and environment models. - The original Mac game stopped gracefully with zero players. A final SQLite backup passed integrity checks; its SHA-256 matched after encrypted transfer and import into the empty live volume. The original 4 accounts, 26 character records and 750 transaction receipts matched exactly. All six territories retained ownership, stock, capture history, victories and unlocked frontier. Normal defender patrols continued after startup.
- The actual public domain served the game, map, wiki and model assets. The downloaded client bundle and character asset matched the built files. HTTPS, secure session cookies and WSS worked. Foreign origins, unauthenticated game connections, private save files and development editor routes were rejected.
- Two synthetic players joined one public world, formed a private party, moved, failed a gathering strike without receiving material, gathered repeatedly without a cooldown, crafted timber and observed replicated staff projectiles and weapon state. The temporary party was removed after testing.
- Chrome completed character creation and tutorial entry, rendered Greyfen and its HUD, and opened crafting and the shared war map. Existing accounts remain available through Sign in; the new domain requires signing in again because browser cookies belong to their original address.
- The VM itself was rebooted. Its boot identity changed; Docker, the game, HTTPS and the backup timer returned automatically. Both test sessions rejoined with exact crafted inventory and party membership retained; password sign-in and reconnect also passed. The Mac game and tunnel stayed stopped throughout.
- An hourly SQLite snapshot was restored to a separate temporary database and passed integrity and record-count checks.
The short public two-player sample measured 29.997 simulation ticks/s, 14.999 snapshots/s and a maximum observed snapshot interval of 115 ms. This is a short network/simulation check, not a player-capacity limit or a promise of lag-free play. Sustained combat, clustered spells, login bursts and larger groups still need load testing before advertising a server capacity. Physical Xbox testing also remains open. Sydney routing, the player's connection and client rendering all affect responsiveness.
Runtime and updates¶
Deployment lives at /opt/fight-the-frontier on the Linux host. deploy/compose.yaml runs one authoritative game container and Caddy. The game has a read-only image, non-root user, a 650 MiB memory limit, a 256 MiB JS heap and a restricted crypto worker pool. Caddy has a 96 MiB limit. Both restart automatically; the game gets 45 seconds for graceful shutdown. Health checks report readiness but do not themselves restart a hung process.
Named volumes preserve campaign state, snapshots and HTTPS certificates. Never run docker compose down --volumes or start two game writers against the campaign. deploy/.env records the exact deployed image tag. Inspect it privately and check the image's org.opencontainers.image.revision label when reviewing a release.
Use the root Dockerfile for a complete Linux build. Build outside active play where possible. The smaller deploy/Dockerfile.runtime is for source/client updates based on a previously verified image; it refuses a changed dependency lockfile. Dependency updates require the complete build. Both paths must use a same-origin production client (VITE_GAME_SERVER=same-origin) and include the rebuilt wiki. Do not include private saves, credentials, Mac dependencies or disposable QA artifacts in an image.
Before replacing the image, validate it with disposable state, take a fresh consistent backup and check active players. Then update the exact release tag, recreate only the game service, and verify health and the changed player journey. Keep the preceding image until acceptance passes. New containers reuse the existing save and certificate volumes.
cd /opt/fight-the-frontier
docker compose --env-file deploy/.env -f deploy/compose.yaml ps
systemctl status fight-the-frontier-backup.timer
systemctl start fight-the-frontier-backup.service
Caddy overwrites X-Frontier-Client-IP with the transport client's address. The game trusts it only from Caddy's exact private address 172.30.50.2; arbitrary forwarded headers and address lists are ignored. Login limits remain separate per client. The original transport address still controls development-only legacy claims. Regression checks cover forged headers and one client exhausting retries without blocking another. This resolves the proxy-wide shared login bucket; it does not establish high-concurrency capacity.
Saves, backups and rollback¶
The live database is /data/campaign.sqlite in the fight-the-frontier-campaign Docker volume. fight-the-frontier-backup.timer runs hourly, creating private, consistent SQLite snapshots in fight-the-frontier-snapshots and retaining seven days. Snapshot files are mode 0600. The helper uses SQLite's backup API, includes committed WAL data, validates integrity and refuses to overwrite an existing snapshot.
Daily DigitalOcean backups are enabled with seven-day retention. The provider's first scheduled backup window is 12 September 2026, 00:00–04:00 UTC. At cutover, no provider backup had yet run; provider-level restore is still unverified. Hourly snapshots on the same VM do not protect against losing that VM by themselves. Check the first provider backup completes and periodically rehearse a restore in isolation.
The original Mac save and a final integrity-checked cutover snapshot remain private on the Mac. They are pre-cutover recovery copies, not current live progress. Source is separately committed and pushed to the private GitHub repository; Git does not back up player data.
For an image rollback, stop the game gracefully, snapshot the newest campaign, verify compatibility, then start the previous image against the same volume. For a database restore, keep the game stopped, preserve the newest database, restore a verified standalone snapshot with UID/GID 1000 and private permissions, and verify accounts and territory before reopening play. Never silently replace newer player progress with the older Mac copy.
The old com.stormfall.playtest launch agent is disabled. Local current-runtime.json now points to the permanent site and records that local hosting is off; its pre-cutover metadata is preserved privately. Only resume Mac hosting during a deliberate migration that first stops the cloud writer and transfers the latest compatible save. Monitor backup failures, disk space, service health, memory, simulation timing and transfer usage.