# Production overrides — used on the VM. # Run with: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d # # Differences from dev: # - MQTT port 1883 is NOT published to the host (stays on the Docker bridge). # Edge nodes reach it via WireGuard tunnel to the Docker bridge IP. # - c2-core and frontend ports are only bound to localhost (Caddy proxies them). # - restart: always (instead of unless-stopped) for hard reboots. services: # ports AND volumes both need !override here, not !reset/a plain list — # compose merges list-type fields by APPENDING across -f files. A plain # list (or !reset on volumes) would leave dev's mosquitto_certs named # volume mounted at /mosquitto/certs alongside this bind mount, and two # mounts targeting the same path is exactly the "address already in use"- # style footgun the c2-core override below already hit once with ports. # mosquitto-data is now a host bind mount too (not just certs) — it holds # dynamic-security.json, the broker's only record of node credentials # (see app/internal/dynsec.py "TWO-SOURCES-OF-TRUTH"). A named Docker # volume already survives normal redeploys (git pull && compose pull && # up -d never passes -v), but the bind mount makes it inspectable/ # backupable the same way the cert directory already is. NOT read-only — # mosquitto writes dynamic-security.json here. mosquitto: restart: always ports: !override - "8883:8883" # TLS only, published. 1883 stays internal (docker bridge, c2-core's own login). volumes: !override - ./drb-c2-core/mosquitto/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro - /opt/drb/mosquitto-data:/mosquitto/data - /opt/drb/mosquitto-certs:/mosquitto/certs:ro # fed by the cert-sync systemd unit, see infra/ansible # !override, not a plain list: compose MERGES `ports` by appending, so a plain # list leaves the base file's "8888:8000" in place alongside this one. The # container then tries to bind 8888 twice — 0.0.0.0 and 127.0.0.1 — and the # second bind fails with "address already in use". It also silently defeated # the whole point of this override, publishing the port on every interface. c2-core: restart: always ports: !override - "127.0.0.1:8888:8000" # Caddy proxies, not exposed publicly discord-bot: restart: always frontend: restart: always ports: !override - "127.0.0.1:3000:3000" # Caddy proxies, not exposed publicly