# infra/ Full stack configuration as deployed on the RPi 3B+ at `192.168.81.147`. ## Layout on host ``` /root/ ├── compose.yaml → infra/compose.yaml ├── mosquitto/config/mosquitto.conf → infra/mosquitto/config/mosquitto.conf ├── zigbee2mqtt/ → infra/zigbee2mqtt/ │ ├── configuration.yaml # device pairings + friendly names + groups │ ├── coordinator_backup.json # zigbee network key + pan id (recovery) │ └── state.json # per-device persisted state (ON/OFF, etc.) └── nodered/ → bind-mount for nodered container's /data ├── flows.json → generated from ../flows/zigbee-monitor.yaml ├── settings.js → infra/nodered/settings.js └── start.sh → infra/nodered/start.sh (patches Dashboard SPA) ``` ## Rebuild procedure from a fresh host 1. Install Docker, `docker compose`. 2. Clone this repo, `cd infra`. 3. `mkdir -p mosquitto/data mosquitto/log` (empty dirs for the volume mounts). 4. `docker compose up -d`. 5. Pair zigbee devices (IEEE addresses in `zigbee2mqtt/configuration.yaml` will be wrong; re-pair or use the existing `coordinator_backup.json` to rejoin the same network). 6. `just deploy` from the repo root to push the Node-RED flow. ## Files that drift at runtime - `nodered/flows.json` — managed by the generator, do not hand-edit. - `nodered/node_modules/@flowfuse/node-red-dashboard/dist/index.html` — patched by `start.sh` at every container start; survives reboots, lost on `docker compose down -v`. - `mosquitto/data/` — broker persistence, transient. - `zigbee2mqtt/database.db` — sqlite, transient (regenerated from `configuration.yaml` + `coordinator_backup.json`). - `zigbee2mqtt/state.json` — committed so device ON/OFF state survives full rebuilds.