|
|
|
@@ -54,78 +54,19 @@ spec:
|
|
|
|
|
# follow-up as any other broker restart (see mosquitto-config.yaml).
|
|
|
|
|
image: eclipse-mosquitto:2.0.22 # {"$imagepolicy": "flux-system:mosquitto"}
|
|
|
|
|
# The shim runs as root (image sets no USER) and prepares the
|
|
|
|
|
# auth files for the broker, which drops to user mosquitto
|
|
|
|
|
# (UID 1883) before reading them — so files must be owned by
|
|
|
|
|
# mosquitto, not root. Across container restarts the emptyDir
|
|
|
|
|
# persists, so the passwd file already exists; rm -f keeps
|
|
|
|
|
# mosquitto_passwd -c (which uses O_EXCL) idempotent.
|
|
|
|
|
# Dynamic Security file for the broker, which drops to user
|
|
|
|
|
# mosquitto (UID 1883) before reading it, so the file must be
|
|
|
|
|
# owned by mosquitto, not root.
|
|
|
|
|
command:
|
|
|
|
|
- sh
|
|
|
|
|
- -c
|
|
|
|
|
- |
|
|
|
|
|
set -eu
|
|
|
|
|
rm -f /mosquitto/auth/passwd
|
|
|
|
|
mosquitto_passwd -c -b /mosquitto/auth/passwd homeassistant "$HA_PASSWORD"
|
|
|
|
|
mosquitto_passwd -b /mosquitto/auth/passwd admin "$ADMIN_PASSWORD"
|
|
|
|
|
mosquitto_passwd -b /mosquitto/auth/passwd sml2mqtt "$SML2MQTT_PASSWORD"
|
|
|
|
|
mosquitto_passwd -b /mosquitto/auth/passwd open3e "$OPEN3E_PASSWORD"
|
|
|
|
|
mosquitto_passwd -b /mosquitto/auth/passwd evcc "$EVCC_PASSWORD"
|
|
|
|
|
mosquitto_passwd -b /mosquitto/auth/passwd zigbee2mqtt "$ZIGBEE2MQTT_PASSWORD"
|
|
|
|
|
# ACL: HA keeps full access (subscribes to everything). Shellies
|
|
|
|
|
# are not legacy users any more: each has its own Dynamic Security
|
|
|
|
|
# account from mqtt-accounts.yaml (REN-802, REN-1017).
|
|
|
|
|
# `admin` is a workstation/debugging credential — full
|
|
|
|
|
# readwrite, kept on its own credential so its password can
|
|
|
|
|
# be rotated independently of the HA session.
|
|
|
|
|
# `sml2mqtt` is the power-meter bridge — WRITE-only under its own
|
|
|
|
|
# `sml2mqtt/#` subtree (it only publishes; HA reads it via the
|
|
|
|
|
# full-access homeassistant user).
|
|
|
|
|
# `open3e` is the Viessmann E3 CAN bridge (Vitocal/VX3) —
|
|
|
|
|
# scoped to its own `open3e/#` subtree: publishes datapoints
|
|
|
|
|
# and later subscribes to `open3e/cmnd` in listener mode (HA
|
|
|
|
|
# reads via the full-access homeassistant user).
|
|
|
|
|
# `evcc` is the (cross-namespace) EV charge controller — reads
|
|
|
|
|
# `open3e/#` (VX3 grid/PV/battery/SoC datapoints), publishes its
|
|
|
|
|
# own state under `evcc/#`, and reads the grid price from
|
|
|
|
|
# `energy/#` (HA republishes input_number.strompreis to
|
|
|
|
|
# energy/tariff/grid; kept OUTSIDE evcc/# so evcc's own retained-
|
|
|
|
|
# topic management can't wipe it).
|
|
|
|
|
cat > /mosquitto/auth/acl <<'EOF'
|
|
|
|
|
user homeassistant
|
|
|
|
|
topic readwrite #
|
|
|
|
|
|
|
|
|
|
user admin
|
|
|
|
|
topic readwrite #
|
|
|
|
|
|
|
|
|
|
user sml2mqtt
|
|
|
|
|
topic write sml2mqtt/#
|
|
|
|
|
|
|
|
|
|
user open3e
|
|
|
|
|
topic readwrite open3e/#
|
|
|
|
|
|
|
|
|
|
user evcc
|
|
|
|
|
topic read open3e/#
|
|
|
|
|
topic readwrite evcc/#
|
|
|
|
|
topic read energy/#
|
|
|
|
|
|
|
|
|
|
# `zigbee2mqtt` is the Zigbee2MQTT bridge (the ZHA replacement).
|
|
|
|
|
# Owns its own `zigbee2mqtt/#` subtree; may WRITE `homeassistant/#`
|
|
|
|
|
# to publish HA MQTT-discovery configs (write-only there, to deny
|
|
|
|
|
# discovery-tree recon from a compromised bridge); and READs `homeassistant/status`, HA's birth/will topic.
|
|
|
|
|
#
|
|
|
|
|
# That read grant does NOT buy a discovery re-publish: on
|
|
|
|
|
# `online`, Z2M 2.12.1 republishes bridge/state and cached device
|
|
|
|
|
# states only (lib/extension/homeassistant.ts onMQTTMessage) —
|
|
|
|
|
# discover() runs solely from start(). The grant is still correct,
|
|
|
|
|
# because the cached-state republish is what makes HA show current
|
|
|
|
|
# values right after an HA restart. Restoring discovery after a
|
|
|
|
|
# BROKER restart is handled by the discovery-guard sidecar in
|
|
|
|
|
# zigbee2mqtt-deployment.yaml.
|
|
|
|
|
user zigbee2mqtt
|
|
|
|
|
topic readwrite zigbee2mqtt/#
|
|
|
|
|
topic write homeassistant/#
|
|
|
|
|
topic read homeassistant/status
|
|
|
|
|
EOF
|
|
|
|
|
# No password_file/acl_file any more (REN-802, REN-1307): every
|
|
|
|
|
# client has its own account in mqtt-accounts.yaml, managed by
|
|
|
|
|
# mqtt-account-controller through Dynamic Security. The last
|
|
|
|
|
# legacy users, the edge-1 bridges sml2mqtt and open3e, moved
|
|
|
|
|
# to the register account edge-1.
|
|
|
|
|
# Dynamic Security start file (REN-802): the controller's seed
|
|
|
|
|
# if it exists, else the static base file. The seed carries
|
|
|
|
|
# every register account and its hash, so the broker is in the
|
|
|
|
@@ -139,43 +80,9 @@ spec:
|
|
|
|
|
cp /mosquitto/config/dynamic-security.json /mosquitto/auth/dynamic-security.json
|
|
|
|
|
echo "dynsec: no seed yet, loaded base file"
|
|
|
|
|
fi
|
|
|
|
|
chown 1883:1883 /mosquitto/auth /mosquitto/auth/passwd /mosquitto/auth/acl /mosquitto/auth/dynamic-security.json
|
|
|
|
|
chmod 0600 /mosquitto/auth/passwd /mosquitto/auth/acl /mosquitto/auth/dynamic-security.json
|
|
|
|
|
chown 1883:1883 /mosquitto/auth /mosquitto/auth/dynamic-security.json
|
|
|
|
|
chmod 0600 /mosquitto/auth/dynamic-security.json
|
|
|
|
|
exec mosquitto -c /mosquitto/config/mosquitto.conf
|
|
|
|
|
env:
|
|
|
|
|
- name: HA_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-credentials
|
|
|
|
|
key: homeassistant-password
|
|
|
|
|
- name: ADMIN_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-admin-credentials
|
|
|
|
|
key: password
|
|
|
|
|
- name: SML2MQTT_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-sml2mqtt-credentials
|
|
|
|
|
key: password
|
|
|
|
|
- name: OPEN3E_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-open3e-credentials
|
|
|
|
|
key: password
|
|
|
|
|
- name: EVCC_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-evcc-credentials
|
|
|
|
|
key: password
|
|
|
|
|
# Zigbee2MQTT bridge credential (mosquitto-zigbee2mqtt-credentials-
|
|
|
|
|
# bootstrap). Hashed into the passwd file here; Z2M reads the same
|
|
|
|
|
# Secret via its init container to authenticate to the broker.
|
|
|
|
|
- name: ZIGBEE2MQTT_PASSWORD
|
|
|
|
|
valueFrom:
|
|
|
|
|
secretKeyRef:
|
|
|
|
|
name: mosquitto-zigbee2mqtt-credentials
|
|
|
|
|
key: password
|
|
|
|
|
ports:
|
|
|
|
|
- name: mqtt
|
|
|
|
|
containerPort: 1883
|
|
|
|
@@ -231,12 +138,12 @@ spec:
|
|
|
|
|
# Service and the probe dials 127.0.0.1; the chain is still checked
|
|
|
|
|
# against mqtt-ca.
|
|
|
|
|
#
|
|
|
|
|
# mosquitto is a single-replica SPOF (HA, Shelly, sml2mqtt, open3e,
|
|
|
|
|
# mosquitto is a single-replica SPOF (HA, Shelly, edge-1 bridge,
|
|
|
|
|
# evcc). Liveness is deliberately slow to fire — failureThreshold 6
|
|
|
|
|
# x 30s = 3 min of sustained failure before a restart — so a
|
|
|
|
|
# transient hiccup never bounces the broker every client depends
|
|
|
|
|
# on. The startupProbe (tcpSocket) suspends both while the
|
|
|
|
|
# container builds the passwd/acl files and mosquitto binds :1883.
|
|
|
|
|
# container copies the Dynamic Security file and mosquitto binds :1883.
|
|
|
|
|
startupProbe:
|
|
|
|
|
tcpSocket:
|
|
|
|
|
port: mqtt
|
|
|
|
|