From 6683f197eb64a59ae5d849d68820f68aaff77b12 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Tue, 21 Jul 2026 11:15:11 +0200 Subject: [PATCH] Document the Docker + Caddy deployment workflow Records the docker compose commands (master key bootstrap, up/down, log tailing) and the SITE_ADDRESS dev-vs-production behavior, plus an explicit warning: app's restart:unless-stopped means a crash mid-round auto-restarts into the still-open scheduler-resume gap, so this isn't unattended-safe yet. Co-Authored-By: Claude Sonnet 5 --- CLAUDE.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index c58fd9e..6508b9e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,6 +34,26 @@ python -m pytest tests/unit/test_hd.py::test_derivation_is_deterministic # run `.env` (gitignored) holds real secrets for local dev; `.env.example` documents the required keys and how to generate them. +## Deployment (Docker + Caddy) + +`docker-compose.yml` runs two containers: `app` (this codebase, built by `Dockerfile`, runs `alembic upgrade head` then `uvicorn`) and `caddy` (reverse proxy + automatic TLS). `.env` still holds the app secrets; `docker-compose.yml` overrides `DATABASE_URL`/`MASTER_KEY_PATH` to point at the bind-mounted `./data/` (db, encrypted master key, logs — all gitignored, persist across container restarts). + +```bash +mkdir -p data/db data/keys data/logs # one-time: host dirs bind-mounted into the app container + +docker compose run --rm app python scripts/generate_master_key.py # one-time: create+encrypt the master xprv into ./data/keys/ + +docker compose up -d --build # build + start app and caddy +docker compose logs -f app # tail app logs (also written to ./data/logs/app.log) +docker compose down # stop +``` + +Caddy's site address comes from `SITE_ADDRESS` (env var on the host, read by `docker-compose.yml`): +- **Dev, no domain**: leave it unset (defaults to `localhost`). Caddy detects it isn't a public hostname and issues a self-signed cert from its own internal CA — browsers will warn on first visit, expected for local testing (`curl -k` or click through). +- **Production, with a domain**: `SITE_ADDRESS=lottery.example.com docker compose up -d` (DNS must already point at the server, ports 80+443 reachable). Caddy automatically requests and renews a real Let's Encrypt certificate — no other config needed. + +Known risk: `docker-compose.yml` sets `restart: unless-stopped` on `app`, so a crash mid-round auto-restarts the container — which hits the scheduler-resume gap below (a round stuck in `closing`/`drawing`/`paying_out` at restart stays stuck). Don't treat this as unattended-safe until that gap is closed. + ## Tech stack (MVP) - **Backend language**: Python.