# DEPLOYMENT.md — building, running and operating the service **Status:** stub written by phase 01 · **Filled in by phase 14**, which measures the real capacity and writes the reverse-proxy/TLS/ops runbook against a production profile. ## Purpose This document covers everything between "a repository" and "players can reach it": the multi-stage container build (A19), the single-service `compose.yaml`, the environment variables an operator actually sets, how TLS and a reverse proxy terminate the WebSocket connection, and the runbook for the failure modes that an in-memory server has. `README.md` "Container" stays the copy-paste quickstart; this file is the reasoning and the operational detail. ## What is deployable today One artifact, one process, no database (A6/A7): the image builds the package with `pip install --prefix=/install .` in a builder stage and copies the result into a slim Python 3.12 runtime that runs as the non-root `player` user (uid 10001), exposes port 8000, and health-checks `GET /healthz` from inside the container. `compose.yaml` runs that one service with `restart: unless-stopped`. Configuration is environment-only — see the README table and `.env.example`; the container sets `UNDERCOOKED_HOST=0.0.0.0` and points `UNDERCOOKED_STATIC_DIR` / `UNDERCOOKED_LEVELS_DIR` at the paths copied into the image, because the source-checkout defaults do not hold under `site-packages`. ```bash podman build -t undercooked -f Containerfile . podman run --rm -p 8000:8000 undercooked podman compose up -d ``` Rules that hold for every deployment of this project: - **Never set `DEBUGPY=1` on a host reachable from outside your machine** — the debugger listener binds `0.0.0.0` (A18, dev-only). - **Never commit `.env`.** It is gitignored, and `.env.example` is the secret-free template; the game has no secrets by design (anonymous, A6/A16). - Everything is in memory: a restart ends every round and erases every scoreboard. That is a documented product decision, not an incident. ## What this document will contain when it is filled in Reverse-proxy configuration (WebSocket upgrade, `Connection: upgrade`, idle timeouts longer than the room's heartbeat), TLS termination and HSTS within the project's `default-src 'self'` CSP (A12), resource limits derived from the phase-12 capacity measurement in `BUDGETS.md`, log/metric surfaces that never record a room code with player contents (§11), a rolling-restart procedure that accepts the round it kills, and the backup story: none, and why.