Files changed: engine/lint-report.md vault/.obsidian/workspace.json vault/runbooks/meshai-prod-compose-override.md
3.3 KiB
| title | type | tags | related | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| meshai prod compose override (cutover state + MeshCore radio) | runbook |
|
|
2026-07-07 |
meshai prod compose override
Backup + restore for docker-compose.override.yml on CT 108 (the meshai
production host). This file is untracked and prod-only — it exists nowhere
but /home/zvx/meshai/work/docker-compose.override.yml, is not in the public
zvx-echo6/meshai repo, and carries no git trace. If the deploy tree is
re-cloned or wiped, production silently reverts to shadow-mode alerts and loses
the MeshCore radio. This runbook is its durable copy.
Docker Compose auto-merges docker-compose.override.yml over the committed
docker-compose.yml, so both settings below are live without any extra flag.
Verbatim contents (as of 2026-07-07)
services:
meshai:
environment:
- MESHAI_CUTOVER_CATEGORIES=earthquake_event,geomagnetic_storm,rf_propagation_alert,avalanche_warning,avalanche_watch,weather_warning,weather_statement,work_zone,road_incident,road_closure,traffic_congestion,stream_flow,wildfire_declared,wildfire_incident,wildfire_closed
devices:
- /dev/meshcore-rak:/dev/meshcore-rak
What each line does
MESHAI_CUTOVER_CATEGORIES— the staged-cutover switch consumed bymeshai/notifications/cutover.py(is_cutover()). Each hazard category is migrated onto the shared formatter+decider pipeline in shadow-only mode first (old handler broadcasts live; new code dry-runs and logs mismatches to/app/data/shadow/<category>.jsonl). Adding a category name here flips it live onto the new formatter+decider and stops the shadow comparison. The list above is effectively the full hazard set → the all-native cutover is complete in prod. Empty/unset = nothing cut over (pure shadow bake). Note: the threewildfire_*categories are also force-enabled directly in code (NATIVE_ALWAYS_DECIDEincutover.py) regardless of this var, because the fire decider itself is the dedup/cooldown gate.devices: /dev/meshcore-rak— passes the RAK4631 MeshCore USB radio on the utility host into the container at a stable udev symlink path. Without it the container cannot see the MeshCore hardware (see meshcore-transport).
Both are deployment state (cutover progress + host-specific device path), which is why they live in an override rather than the committed public compose file.
Restore
# from root@utility (100.64.0.5); zvx has no sudo on CT 108
pct exec 108 -- bash -lc 'cat > /home/zvx/meshai/work/docker-compose.override.yml <<"EOF"
services:
meshai:
environment:
- MESHAI_CUTOVER_CATEGORIES=earthquake_event,geomagnetic_storm,rf_propagation_alert,avalanche_warning,avalanche_watch,weather_warning,weather_statement,work_zone,road_incident,road_closure,traffic_congestion,stream_flow,wildfire_declared,wildfire_incident,wildfire_closed
devices:
- /dev/meshcore-rak:/dev/meshcore-rak
EOF'
# then rebuild/recreate so the merge takes effect
pct exec 108 -- bash -lc 'cd /home/zvx/meshai/work && docker compose up -d'
Verify after restore: docker exec meshai printenv MESHAI_CUTOVER_CATEGORIES
returns the list, and docker exec meshai ls -l /dev/meshcore-rak shows the
device inside the container.