Skip to content

deploy ​

The Compose stack: the whole platform on one host behind one origin. How to run it, its settings, its URLs, backups and what is not production-ready yet are in the Deploying guide.

FileWhat
compose.yamlThe services (preflight, postgres, nakama, minio, api, game, worker, mcp, proxy, creator under its profile: the runner of the platform's own model, and smoke under its: the smoke from inside), their health checks, the volumes, the worker's network with no way out, the game server's WebRTC data channel's UDP ports (off by default: FOI_RTC, published on 127.0.0.1 until FOI_RTC_BIND); the images named ${FOI_IMAGES}-<name>:${FOI_VERSION} (five-on-it-…:local built here, a release's pulled by its bundle, npm run pack:stack). Project name five-on-it.
Dockerfile, Dockerfile.dockerignoreThe images, built from the repository root: node (the Node services, run as TypeScript), proxy (Caddy and the web client's production build), worker (the node image and Blender 5.2.2, pinned to its checksum), nakama (Nakama 3.41 with the platform's runtime module, apps/nakama, built in).
CaddyfileThe proxy: / the web client, /api/* the API without its prefix, /game and /rooms/* the game server's WebSockets, /mcp the MCP server, nothing of the fleet's, the creator runners' or the metrics' private routes, OAuth's routes at the root (/oauth/* and /.well-known/oauth-authorization-server the API's, /.well-known/oauth-protected-resource* the MCP server's); a domain as FOI_SITE_ADDRESS gets a certificate; security headers on every answer. A second site, the documentation at FOI_DOCS_ADDRESS (http://docs.localhost locally): its versions' folders from FOI_DOCS_DIR, /latest/ redirected to the latest's, /live.json the API's /info. Mounted into the proxy, so a host edits it.
.env.exampleEvery setting the stack reads, with placeholders and a comment each; copied to deploy/.env (ignored by git) and given real secrets. The apps run without the stack: the root .env.example.
preflight.mjsThe first service: refuses empty, placeholder or short secrets (only warns with FOI_ALLOW_DEV_SECRETS=1), malformed public URLs, a moderation without its key, and creation on OpenRouter or Claude without its secret, its key or a moderation.
openrouter-key.mjsnpm run openrouter:key: the platform's OpenRouter key's own monthly limit (96 % of FOI_CREATOR_MONTHLY_USD, reset monthly) through OpenRouter's key management API with a management key; a dry run unless --apply (Operations).
stack.mjsnpm run stack:up (build, start, wait until healthy, print the URLs; the preflight's reasons when it refused) and npm run stack:down.
smoke.mjsnpm run stack:smoke: a guest and a creator sign in through Nakama, the creator publishes test-mission-basics's game, the guest opens a room and joins it through the proxy, a player joins the default room, a level is generated from a spec, the MCP server answers and signs in with OAuth; the two become friends through Nakama, a line in the public room reaches the other through the moderation; a city is picked as the main menu does and a test level refused; the web client's build serves its font, a kit and the previews; two regions (one with a town) are built and played; each step timed.
docs/docs-publish.shThe docs host's side of publishing the documentation (docs.yml): the forced command of the docs deploy key (dirs, index, publish, put, latest, prune), nothing outside FOI_DOCS_DIR; shipped in the stack bundle, installed by the fleet's stack-server (Releasing).
postgres/init.sqlMakes Nakama's database beside the platform's when the Postgres volume is created.