From a888125eca550cf6fee1a6eaac0638ca67762d1f Mon Sep 17 00:00:00 2001 From: Julian Cuni Date: Sat, 27 Jun 2026 23:23:11 +0200 Subject: [PATCH] =?UTF-8?q?docs(komodo):=20complete=20env=20reference=20?= =?UTF-8?q?=E2=80=94=20every=20server/vision=20var=20+=20defaults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Stack example only listed the required set; expand it to the FULL reference so an operator can see (and tweak) every env without digging through code. Grouped: - IMAGE SELECTION (REGISTRY, TAG) - REQUIRED (JWT_SECRET, EVENT_SIGNING_KEY, COOKIE_SECURE — no safe default) - COMMONLY SET (VISION_ENABLED, WS_ALLOWED_ORIGINS) - SET BY COMPOSE — don't put in the Stack (VISION_URL, DATABASE_URL, VISION_RECOGNIZER) - OPTIONAL TUNABLES with code defaults: ports, logging/retention, device+printer poll intervals, lane/capture TTLs, and the ANPR knobs incl. this session's new ANPR_POLL_MS=1000 / ANPR_POLL_WINDOW_MS=8000 (raise the window for a slow barrier) - VISION CONTAINER env (the Python service's own VISION_* vars) All defaults pulled from the code (process.env.X ?? default). Documentation only. --- komodo/.env.komodo.example | 101 ++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 14 deletions(-) diff --git a/komodo/.env.komodo.example b/komodo/.env.komodo.example index c4951e0..0d7b9e6 100644 --- a/komodo/.env.komodo.example +++ b/komodo/.env.komodo.example @@ -1,24 +1,97 @@ -# Komodo Stack environment — reference of what a booth Stack needs and WHERE it comes -# from. Under Komodo, plain env lives in the Stack definition (komodo/resources.toml); -# the two SECRETS come from Komodo Core's secret store, PER BOOTH and UNIQUE. This file -# is documentation only — do NOT fill in real secrets here (it would be the same leak -# we're avoiding). See wiki/decisions/fleet-deployment-komodo.md. +# Komodo Stack environment — the COMPLETE reference of every env the booth stack reads: +# required, image-selection, set-by-compose (don't override), and the optional tunables +# with their code defaults. Under Komodo, plain env lives in the Stack definition +# (komodo/resources.toml); the two SECRETS come from Core's secret store, PER BOOTH and +# UNIQUE. This file is DOCUMENTATION — never fill in real secrets here. See +# wiki/decisions/fleet-deployment-komodo.md. +# +# A minimal working Stack only needs: REGISTRY, TAG, the two secrets, COOKIE_SECURE=0, +# VISION_ENABLED=1, WS_ALLOWED_ORIGINS. Everything under "OPTIONAL TUNABLES" has a safe +# default in code — set one only to override it. -# --- plain Stack env (lives in resources.toml; safe in git) ------------------- +# ════════════════════════════════════════════════════════════════════════════ +# IMAGE SELECTION (picks which container image to pull — not server runtime env) +# ════════════════════════════════════════════════════════════════════════════ REGISTRY=git.infra.msai.al/mca/parking_solution # IMMUTABLE per-commit tag. Manual + pinned. Bump per deploy. Never the moving `dev` -# on a production booth. +# on a PRODUCTION booth (a staging booth may track `dev`). TAG=dev-830993b + +# ════════════════════════════════════════════════════════════════════════════ +# REQUIRED (no safe default — the server refuses to boot / login breaks without) +# ════════════════════════════════════════════════════════════════════════════ +# Login signing secret (>=32 chars, no change-me/insecure/dev-only). openssl rand -hex 32. +JWT_SECRET=[[booth__jwt_secret]] +# Ledger-signing HMAC key — the anti-fraud root. DISTINCT per booth; never reuse. If unset +# it falls back to JWT_SECRET (warned). openssl rand -hex 32. +EVENT_SIGNING_KEY=[[booth__event_signing_key]] +# CRITICAL on the plain-HTTP booth LAN: cookies are Secure (HTTPS-only) by DEFAULT, so +# without =0 the auth cookie never sends and operators CANNOT log in. Set 1 only behind TLS. COOKIE_SECURE=0 + +# ════════════════════════════════════════════════════════════════════════════ +# COMMONLY SET (have defaults, but you usually want these explicit on a booth) +# ════════════════════════════════════════════════════════════════════════════ +# Turn the ANPR/vision call on. Default "" (off-ish). Set 1 to enable. (Prod compose also +# forces VISION_RECOGNIZER=fast_alpr on the vision container.) VISION_ENABLED=1 +# Extra origins the booth WebSocket (/api/ws) accepts beyond same-origin. Comma-separated, +# e.g. http://parksystems.msai.al. Blank = only the same-origin booth URL. Default "". WS_ALLOWED_ORIGINS= -# --- secrets (Core secret store, referenced by name in resources.toml) -------- -# Generated PER BOOTH (openssl rand -hex 32), registered in Core under booth-scoped -# names, never reused across sites. The user generates these; they are never typed on -# a CLI or committed. +# ════════════════════════════════════════════════════════════════════════════ +# SET BY COMPOSE — do NOT put these in the Stack (the compose files own them) +# ════════════════════════════════════════════════════════════════════════════ +# VISION_URL=http://127.0.0.1:8089 # prod override (host-net server → loopback vision) +# DATABASE_URL=/data/parking.sqlite # the mounted volume (the signed ledger) +# VISION_RECOGNIZER=fast_alpr # prod override on the vision container + +# ════════════════════════════════════════════════════════════════════════════ +# OPTIONAL TUNABLES — all have code defaults; set only to override. (defaults shown) +# ════════════════════════════════════════════════════════════════════════════ +# --- networking / process --- +# PORT=3000 # server listen port +# HOST=0.0.0.0 # bind interface (127.0.0.1 = loopback only) +# BACKEND_HOST_IP= # override the auto-picked IP devices push back to +# # (multi-NIC hosts; usually auto-detected fine) +# WEB_DIST_DIR= # where the built SPA lives (the image sets it) +# --- logging --- +# LOG_LEVEL=info # debug|info|warn|error +# LOG_RETENTION_DAYS=30 # app_logs auto-purge age +# LOG_RETENTION_MAX_ROWS=50000 # app_logs row cap +# RECYCLE_BIN_RETENTION_DAYS=30 # soft-deleted items auto-purge age (0 = keep forever) +# --- device monitor / lane --- +# DEVICE_POLL_MS=8000 # device health poll interval +# PRINTER_POLL_MS=5000 # printer status poll interval +# LANE_BUSY_TTL_MS=30000 # how long a lane stays "busy" after a vehicle push +# CAPTURE_TTL_MS=30000 # snapshot evidence cache TTL +# --- ANPR / vision (server side) --- +# VISION_URL is compose-set (above). These are the knobs you may tweak per booth: +# VISION_TIMEOUT_MS=1500 # per /analyze call timeout +# VISION_MIN_CONFIDENCE=0.5 # advisory floor (telemetry/lane); below = low_confidence +# VISION_ENTRY_MIN_CONFIDENCE=0.85 # STRICT barrier-driving floor (auto entry/exit). A +# # read below this is ignored (falls back to card/QR). +# ANPR_DEBOUNCE_MS=12000 # same plate/camera within this = one presentation +# ANPR_POLL_MS=1000 # poll-until-confident: re-pull a fresh frame every N ms +# ANPR_POLL_WINDOW_MS=8000 # ...for up to this long while the car sits at the +# # barrier. RAISE if a slow barrier means the car +# # waits >8s before the plate reads clean. + +# ════════════════════════════════════════════════════════════════════════════ +# VISION CONTAINER env (the Python ANPR service — its OWN process, prefix VISION_) +# Mostly compose-set; documented here for completeness. (defaults shown) +# ════════════════════════════════════════════════════════════════════════════ +# VISION_RECOGNIZER=fast_alpr # stub | fast_alpr (prod compose forces fast_alpr) +# VISION_HOST=0.0.0.0 # bind (prod publishes 127.0.0.1 only — see compose) +# VISION_PORT=8089 +# VISION_DETECTOR_MODEL=yolo-v9-t-384-license-plate-end2end +# VISION_OCR_MODEL=cct-xs-v2-global-model +# VISION_MIN_CONFIDENCE=0.5 # the Python service's own floor (keep ~in sync w/ server) + +# ════════════════════════════════════════════════════════════════════════════ +# SECRETS — referenced by name in resources.toml, stored in Core (never inline here) +# ════════════════════════════════════════════════════════════════════════════ # JWT_SECRET -> [[booth__jwt_secret]] (login) # EVENT_SIGNING_KEY -> [[booth__event_signing_key]] (ledger signing — fraud root) -# Periphery/registry auth also live in Core: -# periphery passkey -> [[periphery_passkey_booth_]] -# registry account -> [[gitea_registry_account]] +# periphery passkey -> [[periphery_passkey_booth_]] (agent onboarding) +# registry account -> [[gitea_registry_account]] (image pull)