docs(wiki): session context — first booth go-live (user split, Docker deploy, web access)

appliance-provisioning.md: new §5c (admin/operator OS user split — verified; strip
lxd/lpadmin/docker from the operator) + fleshed-out §6 runtime (resolute codename caveat,
the standalone deploy dir + .env, the deploy commands, seed-admin, healthy-startup signal,
and the web-access gotchas). log.md: the [2026-06-23] go-live entry (CI uv fix, compose env
passthrough, relative /api, Caddy proxy). Container-deployment "Web access" section already
landed last commit.

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-23 19:29:36 +02:00
parent aa546235fb
commit f9bd586265
2 changed files with 85 additions and 8 deletions
+24
View File
@@ -1516,3 +1516,27 @@ prompts for admin+password. OS hardening on unit 1 is now COMPLETE: LUKS FDE + T
step, §5b further-hardening TODO: SSH key-only, kiosk lockdown, signing key→TPM, autoremove old
kernel) + [[disk-os-hardening]]. STILL TODO on the box: Docker install + run the parking stack (needs
the images pushed — dev push + registry secrets pending).
## [2026-06-23] deploy | First booth GO-LIVE — Docker stack running + web-access fixes (CI uv, compose env, relative /api, Caddy)
Deployed the two images onto the hardened booth (Dell 7070, Ubuntu 26.04) and worked through the
real-world bring-up issues. (1) Operator/admin OS user split: created a dedicated sudo `admin` user,
removed the auto-login operator from `sudo` (and should drop `lxd`/`lpadmin` — lxd is a root-escape
path); admin is the only sudo, operator auto-logs in unprivileged. (2) Docker 29.6 installed; deploy
dir /opt/parking_solution with hand-copied compose + .env; registry login to git.infra.msai.al; the
stack came up clean — vision fast_alpr loaded from the BAKED cache (0 downloads → offline-first
confirmed on real hardware), server migrated /data, both healthy. (3) Seeded the first admin via
`docker compose exec server node scripts/seed-admin.mjs` (bcrypt, writes users table — NOT the signed
ledger). FIXES committed this session: CI `astral-sh/setup-uv` action failed on the Gitea runner →
install uv via its official curl script instead (both ci.yml + build-images.yml) [0a22eab]; the base
compose only forwarded JWT_SECRET/DATABASE_URL/VISION_URL → added COOKIE_SECURE (CRITICAL on plain-
http or login cookies never send), WS_ALLOWED_ORIGINS, EVENT_SIGNING_KEY, VISION_ENABLED [1092316];
the SPA had VITE_API_BASE=http://127.0.0.1:3000 baked in (leaked from apps/web/.env.production, which
is for the TAURI build but Vite auto-loads it for every build) → server Dockerfile now empties it via
.env.production.local so the SPA uses RELATIVE /api and works from ANY host [77b2acb]; added a CADDY
reverse proxy (prod override) so the booth is reached on a clean port-80 URL, server goes internal,
Caddyfile binds :80 to match any hostname incl. parksystems.msai.al [c637b27]. NET RESULT: no domain
baked into any image — naming controlled by hosts/DNS on-site; admin can reach it from another LAN PC.
Verified the relative-/api + Caddy fix end-to-end locally (Host: parksystems.msai.al through :80 →
SPA + /api/auth/login reach the server, no CORS). See [[container-deployment]] "Web access",
[[appliance-provisioning]]. REMAINING on the box: push dev so CI rebuilds parking-server:dev with the
relative-/api fix, then pull on the booth; kiosk autostart; operator user lxd/lpadmin cleanup.