feat(deploy): booth.sh wrapper over the compose files + update flow

The booth PC (Ubuntu) needs one command instead of the long
`docker compose -f docker-compose.yml -f docker-compose.prod.yml --env-file .env …`
over the three compose files.

scripts/booth.sh — prod by default (ENV=dev for the dev override):
up/down/restart/status/logs/pull/config/exec, plus the requested `update` =
pull the moving branch tag → up -d --remove-orphans (recreates only
digest-changed services; named volumes / the SQLite ledger are preserved) →
docker image prune. Prod refuses to run without .env (no safe JWT_SECRET
default); dev with no .env injects the documented benign local secret (the
base file makes JWT_SECRET shell-required via ${JWT_SECRET:?}). down never
passes -v (would wipe the signed-ledger volume); help/unknown-command
short-circuit before any Docker/.env requirement.

.env.example — the vars the compose files consume (REGISTRY, TAG, JWT_SECRET,
EVENT_SIGNING_KEY, COOKIE_SECURE=0, WS_ALLOWED_ORIGINS). .env stays gitignored.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-24 20:38:44 +02:00
parent 6d7682ab4a
commit 50dd554b43
2 changed files with 205 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
# Booth deploy env — copy to `.env` and fill in, then run ./scripts/booth.sh up
# (prod). Consumed by docker-compose.yml + the prod override via --env-file.
# See wiki/decisions/container-deployment.md. Do NOT commit the filled-in .env.
# --- image source (prod pulls from the house Gitea registry) ------------------
# The registry namespace; combined with the image name + TAG below.
REGISTRY=git.infra.msai.al/mca/parking_solution
# Moving branch tag to deploy: `main` for production, `dev` for staging. A push to
# that branch republishes this tag, so `booth.sh update` pulls the latest of it.
TAG=main
# --- secrets (NO safe defaults — the server refuses to boot without a real one) -
# JWT signing secret. Generate yourself, never share it: openssl rand -hex 32
# Must be 32+ chars and must NOT contain change-me / insecure / dev-only.
JWT_SECRET=
# Ledger-signing key for the append-only signed event chain. Set a DISTINCT value
# in prod (don't reuse JWT_SECRET). openssl rand -hex 32
EVENT_SIGNING_KEY=
# --- booth LAN specifics ------------------------------------------------------
# Auth cookie is HTTPS-only by default; the booth is plain HTTP behind Caddy on
# :80, so this MUST stay 0 or operators cannot log in. Set to 1 only behind TLS.
COOKIE_SECURE=0
# Remote origins the live WS feed must accept (same-origin always passes). Add any
# address admins hit the UI from beyond the booth itself, comma-separated, e.g.
# http://parksystems.msai.al (leave blank if only the local booth URL is used).
WS_ALLOWED_ORIGINS=
# Vision/ANPR. Prod override already forces the fast_alpr engine; leave VISION_ENABLED=1
# unless you are running without the camera. (Set 0 to disable the vision call entirely.)
VISION_ENABLED=1