Files
nr-flow-validator/infra/compose.yaml
T
david 36f9d0a284 party-lock: add MQTT ACL-based plug lock service
Listener watches party-lock/<plug>/set and dynamically generates
mosquitto ACL deny rules. Test against bamboo first, then dj-booth.
Add lock button to CYD dashboard.
2026-07-02 20:04:11 -07:00

162 lines
5.0 KiB
YAML

services:
mosquitto:
image: eclipse-mosquitto:latest
container_name: mosquitto
restart: unless-stopped
user: "1883:1883"
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
zigbee2mqtt:
image: ghcr.io/pine64/zigbee2mqtt:latest-dev # BLZ fork, NOT koenkk
container_name: zigbee2mqtt
restart: unless-stopped
depends_on:
- mosquitto
ports:
- "8080:8080"
volumes:
- ./zigbee2mqtt:/app/data
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
environment:
TZ: America/Los_Angeles
# govee2mqtt:
# image: ghcr.io/wez/govee2mqtt:latest
# container_name: govee2mqtt
# restart: unless-stopped
# network_mode: host
# environment:
# GOVEE_EMAIL: your@email.com
# GOVEE_PASSWORD: yourpassword
# GOVEE_API_KEY: your-api-key
# MQTT_HOST: 127.0.0.1
# TZ: America/Los_Angeles
#
nodered:
build: ./nodered
container_name: nodered
restart: unless-stopped
depends_on:
- mosquitto
user: "1000:1000"
ports:
- "1880:1880"
volumes:
- ./nodered:/data # bind: settings.js, flows.json, start.sh, package.json
- /data/node_modules # anonymous: preserves build-time npm install
environment:
TZ: America/Los_Angeles
DASHBOARD_BASE_HREF: /dashboard/
command: ["sh", "/data/start.sh"]
# Listens to ntfy.sh for doorbell events and toggles a smart plug on each alert.
# Topic: ALERT_klubhaus_topic_test (matches ESP32 firmware DEBUG_MODE suffix)
# Action: TOGGLE on zigbee2mqtt/Sideboard Lamp/set
# On a fresh alert, flash the plug: N toggles spaced FLASH_INTERVAL_SECONDS
# so the total runtime is FLASH_DURATION_SECONDS.
doorbell-listener:
build: ./doorbell-listener
container_name: doorbell-listener
restart: unless-stopped
depends_on:
- mosquitto
volumes:
- ./doorbell-listener/state:/data/doorbell-listener
environment:
MQTT_HOST: mosquitto
MQTT_PORT: "1883"
PLUG_TOPIC: "zigbee2mqtt/Sideboard Lamp/set"
POLL_INTERVAL: "5"
MAX_AGE_SECONDS: "180"
FLASH_INTERVAL_SECONDS: "1"
FLASH_DURATION_SECONDS: "14"
TZ: America/Los_Angeles
# Audio router: PipeWire + WirePlumber + PulseAudio bridge + BlueZ.
# Routes audio from librespot / mopidy / phone-Bluetooth to USB DAC (Q5K)
# via ALSA. Falls back to RPi 3.5mm / HDMI if no USB DAC.
# PEQ is applied on the DAC side (Q5K's Qudelix app, 20 bands), not here.
# NOTE: /run/dbus + /run/user/0 use tmpfs (NOT host bind-mount) — the host's
# dbus socket is /run/dbus/system_bus_socket and bind-mounting our container's
# socket overwrites it, breaking dockerd's ability to talk to systemd.
audio-bridge:
build: ./audio-bridge
container_name: audio-bridge
restart: unless-stopped
privileged: true
network_mode: host
devices:
- /dev/snd:/dev/snd
tmpfs:
- /run/dbus:size=1M
- /run/user/0:size=1M
cap_add:
- SYS_ADMIN # bluetoothd needs CAP_SYS_ADMIN for HCI
- NET_ADMIN
# Spotify Connect: phone's Spotify app shows "Klubhaus" as a Connect target.
# Outputs audio to audio-bridge via PulseAudio (TCP localhost:4713).
# Built locally on RPi (cross-compile is too slow under qemu).
librespot:
build: ./librespot
image: infra-librespot:latest
container_name: librespot
restart: unless-stopped
depends_on:
- audio-bridge
network_mode: host
# CMD is set in Dockerfile; do not override here.
volumes:
- librespot_cache:/var/cache/librespot
# Mopidy: Qobuz + local files + internet radio. Web UI on http://rpi:6680.
# Outputs audio to audio-bridge via PulseAudio (localhost:4713).
# Get Qobuz app_id + secret from https://developer.qobuz.com/api/v1/oauth
# Built locally from python:3.12-slim + pip install (no ghcr.io image).
mopidy:
build: ./mopidy
image: infra-mopidy:latest
container_name: mopidy
restart: unless-stopped
depends_on:
- audio-bridge
network_mode: host
ports:
- "6680:6680"
volumes:
- ./mopidy/data:/var/lib/mopidy
- ./mopidy/music:/music # drop FLACs in infra/mopidy/music/
environment:
TZ: America/Los_Angeles
QOBUZ_APP_ID: "${QOBUZ_APP_ID:-}"
QOBUZ_APP_SECRET: "${QOBUZ_APP_SECRET:-}"
QOBUZ_USERNAME: "${QOBUZ_USERNAME:-}"
QOBUZ_PASSWORD: "${QOBUZ_PASSWORD:-}"
# Party lock: blocks state changes to DJ Booth plug when locked.
# Watches party-lock/dj-booth/set and swaps mosquitto ACL file.
party-lock:
build: ./party-lock
container_name: party-lock
restart: unless-stopped
depends_on:
- mosquitto
volumes:
- ./mosquitto/config:/mosquitto/config
- /var/run/docker.sock:/var/run/docker.sock
environment:
MQTT_HOST: mosquitto
MQTT_PORT: "1883"
TZ: America/Los_Angeles
volumes:
librespot_cache: