furtka-apps/apps/zigbee2mqtt/docker-compose.yaml
Daniel Maksymilian Syrnicki 3408e1aad8
All checks were successful
CI / validate (pull_request) Successful in 6s
CI / shellcheck (pull_request) Successful in 13s
feat: add mosquitto + zigbee2mqtt dependency pair
First catalog apps to exercise core 26.17's app-to-app dependency
feature — until now every app was standalone.

- mosquitto: MQTT broker, first dependency *provider*. Mandatory auth;
  per-consumer accounts created by on_install/on_start hooks
  (scripts/provision-client.sh, scripts/ensure-client.sh) that run inside
  the broker container via `docker compose exec`. Provider-side password
  stash so on_start can restore an account after a volume wipe.
- zigbee2mqtt: first dependency *consumer*. `requires` mosquitto; MQTT
  creds wired in from the provisioning hook via ZIGBEE2MQTT_CONFIG_* env.
  Serial coordinator path as a text setting + devices mapping.

Supporting changes:
- Bump vendored furtka_manifest.py (26.10-era -> 26.17) so the validator
  actually validates the `requires` schema instead of ignoring it.
- Document `requires`/hooks in apps/README.md (was undocumented), including
  the three framework gaps building this pair surfaced.
- CI now shellchecks app hook scripts (apps/*/scripts/*.sh), not just
  repo-root scripts/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-28 23:45:27 +02:00

50 lines
2.2 KiB
YAML

# Furtka Zigbee2MQTT — Zigbee-to-MQTT bridge (dependency consumer).
#
# Declares `requires: [{app: mosquitto, ...}]` in manifest.json. Installing
# this app pulls in mosquitto first; mosquitto's provision-client.sh hook then
# creates a dedicated MQTT account and writes MQTT_SERVER / MQTT_USER /
# MQTT_PASS into THIS app's .env before the container below starts. We feed
# those into zigbee2mqtt via its ZIGBEE2MQTT_CONFIG_* env overrides, so no
# configuration.yaml has to be templated by hand.
#
# host.docker.internal: the broker runs in a separate compose project on a
# separate network, so we reach its host-published 1883 via the docker
# host-gateway. The hook hands us mqtt://host.docker.internal:1883 to match.
#
# Hardware: zigbee2mqtt needs a physical Zigbee USB coordinator. ${ZIGBEE_SERIAL_PORT}
# is a required text setting (a `path`-type setting can't express a /dev node:
# the validator rejects non-directories and the /dev deny-list). The `devices`
# entry maps that host device into the container. The `:-/dev/null` fallback is
# ONLY so `docker compose config` (catalog validation, run with no .env) parses
# cleanly; a real install always has the device set. On a box with no stick
# attached the container won't fully come up — it still connects to MQTT first,
# which is enough to confirm the dependency/credential handshake.
#
# Port 8084 on the host -> 8080 in the container (8080 is taken by it-tools).
#
# TODO(image-pin): pin to a digest once verified against the upstream registry.
services:
zigbee2mqtt:
image: koenkk/zigbee2mqtt:1.42.0
restart: unless-stopped
ports:
- "8084:8080"
environment:
- TZ=Europe/Berlin
- ZIGBEE2MQTT_CONFIG_MQTT_SERVER=${MQTT_SERVER}
- ZIGBEE2MQTT_CONFIG_MQTT_USER=${MQTT_USER}
- ZIGBEE2MQTT_CONFIG_MQTT_PASSWORD=${MQTT_PASS}
- ZIGBEE2MQTT_CONFIG_SERIAL_PORT=${ZIGBEE_SERIAL_PORT}
- ZIGBEE2MQTT_CONFIG_FRONTEND_ENABLED=true
- ZIGBEE2MQTT_CONFIG_FRONTEND_PORT=8080
devices:
- ${ZIGBEE_SERIAL_PORT:-/dev/null}:${ZIGBEE_SERIAL_PORT:-/dev/null}
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- furtka_zigbee2mqtt_data:/app/data
volumes:
furtka_zigbee2mqtt_data:
external: true