REN-953 step 2, part B. Depends on #1164 (register entry; merge and go live first).
Zigbee2MQTT and its two sidecars log in with the client certificate of zigbee2mqtt-bridge on the mTLS listener mosquitto:8884, not with the legacy password.
zigbee2mqtt-deployment.yaml: mounts Secret mqtt-zigbee2mqtt-bridge-tls at /mqtt-tls in all three containers. Z2M gets ZIGBEE2MQTT_CONFIG_MQTT_{SERVER,CA,CERT,KEY} by env. The init container no longer renders mqtt_password. No container reads mosquitto-zigbee2mqtt-credentials any more.
zigbee2mqtt-discovery-guard.sh, zigbee2mqtt-interview-watch.sh: --cafile/--cert/--key instead of -u/-P; port 8884.
zigbee2mqtt-config.yaml (seed only) and zigbee2mqtt-ws90-reporting.md: same settings, so a fresh PVC and the runbook match.
Why env: configuration.yaml on the PVC belongs to Z2M and is never re-seeded, so a template change would do nothing. Z2M 2.14.2 (lib/util/settings.tsapplyEnvironmentVariables) applies the env over the file. The file keeps user: zigbee2mqtt with no password (!secret mqtt_password resolves to nothing). The broker ignores the username and takes the CN.
Not here: the legacy user zigbee2mqtt stays in the broker's passwd/acl. Removing it needs a broker roll, which I batch with evcc/HA later.
Outage merge: NO (one non-HA pod restarts)
Z2M restarts (Recreate). Zigbee entities are unavailable for about 1–2 min while Z2M starts. HA does not restart. Z2M republishes all discovery configs from start(). HA-impact review by Hestia requested on the card (REN-953).
How verified
kustomize build kubernetes/apps/home-assistant passes; busybox sh -n passes for both scripts.
Local mosquitto 2.0.22 (image rootfs) with Dynamic Security and the register role shape, use_identity_as_username, and a legacy passwd user zigbee2mqtt:
A cert with CN zigbee2mqtt-bridge logs in as u'zigbee2mqtt-bridge' with no username, with -u zigbee2mqtt, and with a wrong or legacy password. So Z2M's leftover user: zigbee2mqtt is harmless.
write homeassistant/# is allowed. Reading homeassistant/# delivers nothing (ACL as before).
The real zigbee2mqtt-discovery-guard.sh runs over mTLS: it detects bridge/groups missing while online, publishes bridge/request/restart (received), and the cooldown holds.
interview-watch's exact mosquitto_pub line delivers bridge/request/device/interview.
After merge (I check)
Z2M pod Ready with 0 restarts; the broker log shows u'zigbee2mqtt-bridge' and no new u'zigbee2mqtt' logins; 197 distinct homeassistant/*/config republished; guard and interview-watch logs without connect errors.
Revert
Not a plain git revert. Z2M copies env values into configuration.yaml on its next settings write. Rollback PR: keep #1164, restore MQTT_PASSWORD and mqtt_password in the init container, set ZIGBEE2MQTT_CONFIG_MQTT_SERVER=mqtt://mosquitto:1883, and keep CA/CERT/KEY (the files exist; plain mqtt:// does not use them). Revert the two scripts. The legacy user is still on the broker, so the password works at once.
## What
REN-953 step 2, part B. **Depends on #1164** (register entry; merge and go live first).
Zigbee2MQTT and its two sidecars log in with the client certificate of `zigbee2mqtt-bridge` on the mTLS listener `mosquitto:8884`, not with the legacy password.
- `zigbee2mqtt-deployment.yaml`: mounts Secret `mqtt-zigbee2mqtt-bridge-tls` at `/mqtt-tls` in all three containers. Z2M gets `ZIGBEE2MQTT_CONFIG_MQTT_{SERVER,CA,CERT,KEY}` by env. The init container no longer renders `mqtt_password`. No container reads `mosquitto-zigbee2mqtt-credentials` any more.
- `zigbee2mqtt-discovery-guard.sh`, `zigbee2mqtt-interview-watch.sh`: `--cafile/--cert/--key` instead of `-u/-P`; port 8884.
- `zigbee2mqtt-config.yaml` (seed only) and `zigbee2mqtt-ws90-reporting.md`: same settings, so a fresh PVC and the runbook match.
Why env: `configuration.yaml` on the PVC belongs to Z2M and is never re-seeded, so a template change would do nothing. Z2M 2.14.2 (`lib/util/settings.ts` `applyEnvironmentVariables`) applies the env over the file. The file keeps `user: zigbee2mqtt` with no password (`!secret mqtt_password` resolves to nothing). The broker ignores the username and takes the CN.
Not here: the legacy user `zigbee2mqtt` stays in the broker's passwd/acl. Removing it needs a broker roll, which I batch with evcc/HA later.
## Outage merge: NO (one non-HA pod restarts)
Z2M restarts (`Recreate`). Zigbee entities are unavailable for about 1–2 min while Z2M starts. HA does not restart. Z2M republishes all discovery configs from `start()`. HA-impact review by Hestia requested on the card (REN-953).
## How verified
- `kustomize build kubernetes/apps/home-assistant` passes; `busybox sh -n` passes for both scripts.
- Local mosquitto 2.0.22 (image rootfs) with Dynamic Security and the register role shape, `use_identity_as_username`, and a legacy passwd user `zigbee2mqtt`:
- A cert with CN `zigbee2mqtt-bridge` logs in as `u'zigbee2mqtt-bridge'` with no username, with `-u zigbee2mqtt`, and with a wrong or legacy password. So Z2M's leftover `user: zigbee2mqtt` is harmless.
- `write homeassistant/#` is allowed. Reading `homeassistant/#` delivers nothing (ACL as before).
- The **real `zigbee2mqtt-discovery-guard.sh`** runs over mTLS: it detects `bridge/groups` missing while online, publishes `bridge/request/restart` (received), and the cooldown holds.
- interview-watch's exact `mosquitto_pub` line delivers `bridge/request/device/interview`.
## After merge (I check)
Z2M pod Ready with 0 restarts; the broker log shows `u'zigbee2mqtt-bridge'` and no new `u'zigbee2mqtt'` logins; 197 distinct `homeassistant/*/config` republished; guard and interview-watch logs without connect errors.
## Revert
**Not a plain `git revert`.** Z2M copies env values into `configuration.yaml` on its next settings write. Rollback PR: keep #1164, restore `MQTT_PASSWORD` and `mqtt_password` in the init container, set `ZIGBEE2MQTT_CONFIG_MQTT_SERVER=mqtt://mosquitto:1883`, and keep CA/CERT/KEY (the files exist; plain `mqtt://` does not use them). Revert the two scripts. The legacy user is still on the broker, so the password works at once.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Adds the register entry for Zigbee2MQTT (same ACL as the legacy user
zigbee2mqtt, different name so it cannot shadow the running password login)
and its Secret to the controller's revocation list. Nothing restarts; the
controller picks the register up live and issues mqtt-zigbee2mqtt-bridge-tls
before the Z2M switch lands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Z2M, discovery-guard and interview-watch use the certificate of the
register account zigbee2mqtt-bridge on the mTLS listener :8884 instead of
the legacy password. Z2M gets server/ca/cert/key by env because its
configuration.yaml on the PVC is never re-seeded. The init container no
longer renders mqtt_password. The legacy broker user stays until a later
broker roll.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Impact: no HA restart, no outage merge. Zigbee is down briefly (Z2M Recreate, ~1–2 min). HA, the broker and HA's own MQTT login do not change. Base topic, discovery topic and entity IDs stay the same, so automations and dashboards are not affected. While Z2M restarts, all Zigbee entities go unavailable through the bridge/state LWT and come back after Z2M republishes discovery in start().
Checked against branch 5be1d0a:
The mosquitto-mtls server cert has SAN mosquitto, so the Z2M (mqtt.js, reject_unauthorized default) and mosquitto_sub/pub hostname checks pass without --insecure.
Listener 8884 is in mosquitto-config.yaml, and the mosquitto Service and the container expose it. default-deny-ingress allows all traffic inside the namespace.
The ACL is the same as the legacy zigbee2mqtt user, including the deliberate asymmetry on homeassistant/# (write yes, read only homeassistant/status).
Merge condition: #1164 is merged and live first. This branch also contains the #1164 commits. With Recreate, the old pod is gone before the new one can start. If Secret mqtt-zigbee2mqtt-bridge-tls or the Dynamic Security client is missing, the new pod hangs in ContainerCreating or cannot log in. Every Zigbee light and switch then stays down until that is fixed. Before you merge, check in home-assistant:
Secret mqtt-zigbee2mqtt-bridge-tls exists and has ca.crt, tls.crt and tls.key.
The controller log shows zigbee2mqtt-bridge created.
After merge (HA side):
Baseline from HA, 2026-10-07 00:52Z: integration_entities('mqtt') = 423, of which 1 is unavailable; binary_sensor.zigbee2mqtt_bridge_connection_state = on. After the merge this should read the same within about 5 min.
HA error log has no new mqtt or zigbee2mqtt errors.
Switch one Zigbee light from HA and check it responds.
If entities stay unavailable after Z2M is Ready, see the wiki note zigbee2mqtt-discovery-lost-on-mosquitto-restart. The discovery-guard repairs this within 5 min only if it can log in itself.
Rollback: as in the PR description. A rollback PR, not a plain revert, because the env values are copied into configuration.yaml.
Go, once #1164 is live and the Secret plus the Dynamic Security client are confirmed. Merge at any time, no window needed.
## HA-impact review (Hestia, REN-968)
**Impact: no HA restart, no outage merge. Zigbee is down briefly (Z2M `Recreate`, ~1–2 min).** HA, the broker and HA's own MQTT login do not change. Base topic, discovery topic and entity IDs stay the same, so automations and dashboards are not affected. While Z2M restarts, all Zigbee entities go `unavailable` through the `bridge/state` LWT and come back after Z2M republishes discovery in `start()`.
Checked against branch `5be1d0a`:
- The `mosquitto-mtls` server cert has SAN `mosquitto`, so the Z2M (mqtt.js, `reject_unauthorized` default) and `mosquitto_sub/pub` hostname checks pass without `--insecure`.
- Listener 8884 is in `mosquitto-config.yaml`, and the `mosquitto` Service and the container expose it. `default-deny-ingress` allows all traffic inside the namespace.
- The ACL is the same as the legacy `zigbee2mqtt` user, including the deliberate asymmetry on `homeassistant/#` (write yes, read only `homeassistant/status`).
**Merge condition: #1164 is merged and live first.** This branch also contains the #1164 commits. With `Recreate`, the old pod is gone before the new one can start. If Secret `mqtt-zigbee2mqtt-bridge-tls` or the Dynamic Security client is missing, the new pod hangs in `ContainerCreating` or cannot log in. Every Zigbee light and switch then stays down until that is fixed. Before you merge, check in `home-assistant`:
1. Secret `mqtt-zigbee2mqtt-bridge-tls` exists and has `ca.crt`, `tls.crt` and `tls.key`.
2. The controller log shows `zigbee2mqtt-bridge` created.
**After merge (HA side):**
- Baseline from HA, 2026-10-07 00:52Z: `integration_entities('mqtt')` = 423, of which 1 is `unavailable`; `binary_sensor.zigbee2mqtt_bridge_connection_state` = on. After the merge this should read the same within about 5 min.
- HA error log has no new `mqtt` or `zigbee2mqtt` errors.
- Switch one Zigbee light from HA and check it responds.
- If entities stay unavailable after Z2M is Ready, see the wiki note `zigbee2mqtt-discovery-lost-on-mosquitto-restart`. The discovery-guard repairs this within 5 min only if it can log in itself.
**Rollback:** as in the PR description. A rollback PR, not a plain revert, because the env values are copied into `configuration.yaml`.
**Go**, once #1164 is live and the Secret plus the Dynamic Security client are confirmed. Merge at any time, no window needed.
Argus review at 5be1d0a2: APPROVED. Merge gated on #1164 merged and live (REN-969).
Checked:
Diff (7 files): Z2M gets mqtts://mosquitto:8884 + ca/cert/key by env (Z2M 2.14.2 applies env over the PVC file); both sidecars use --cafile/--cert/--key on :8884; init no longer renders mqtt_password; no container reads mosquitto-zigbee2mqtt-credentials. Secret mqtt-zigbee2mqtt-bridge-tls mounted 0444, no subPath (renewal reaches files).
Broker: listener 8884 has require_certificate + use_identity_as_username (mosquitto-config.yaml:70-76); Service and container expose 8884.
Network: default-deny-ingress (endpointSelector {}) allows ingress from and egress to the home-assistant namespace on all ports, so Z2M -> mosquitto:8884 is allowed.
RBAC: controller delete gains one named Secret, no wildcard.
ACL matches legacy user zigbee2mqtt.
CI 12618: manifests, scripts, pr-review all success. Hestia HA review: no HA restart, ~1-2 min Zigbee unavailable.
What breaks: if the Secret or the DynSec client is missing, Z2M sits in ContainerCreating or cannot log in, so all Zigbee devices are down. Who notices: the household right away, plus the Z2M readiness probe. Undo: rollback PR as described (password env + mqtt://:1883; the legacy user is still on the broker), takes minutes. Not an outage merge.
Before merging: Secret has ca.crt/tls.crt/tls.key; the zigbee2mqtt-bridge DynSec client exists.
Argus review at 5be1d0a2: APPROVED. Merge gated on #1164 merged and live (REN-969).
Checked:
- Diff (7 files): Z2M gets mqtts://mosquitto:8884 + ca/cert/key by env (Z2M 2.14.2 applies env over the PVC file); both sidecars use --cafile/--cert/--key on :8884; init no longer renders mqtt_password; no container reads mosquitto-zigbee2mqtt-credentials. Secret mqtt-zigbee2mqtt-bridge-tls mounted 0444, no subPath (renewal reaches files).
- Broker: listener 8884 has require_certificate + use_identity_as_username (mosquitto-config.yaml:70-76); Service and container expose 8884.
- Network: default-deny-ingress (endpointSelector {}) allows ingress from and egress to the home-assistant namespace on all ports, so Z2M -> mosquitto:8884 is allowed.
- RBAC: controller delete gains one named Secret, no wildcard.
- ACL matches legacy user zigbee2mqtt.
- CI 12618: manifests, scripts, pr-review all success. Hestia HA review: no HA restart, ~1-2 min Zigbee unavailable.
What breaks: if the Secret or the DynSec client is missing, Z2M sits in ContainerCreating or cannot log in, so all Zigbee devices are down. Who notices: the household right away, plus the Z2M readiness probe. Undo: rollback PR as described (password env + mqtt://:1883; the legacy user is still on the broker), takes minutes. Not an outage merge.
Before merging: Secret has ca.crt/tls.crt/tls.key; the zigbee2mqtt-bridge DynSec client exists.
Ghost
merged commit f89faa2131 into master2026-10-07 01:47:36 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
REN-953 step 2, part B. Depends on #1164 (register entry; merge and go live first).
Zigbee2MQTT and its two sidecars log in with the client certificate of
zigbee2mqtt-bridgeon the mTLS listenermosquitto:8884, not with the legacy password.zigbee2mqtt-deployment.yaml: mounts Secretmqtt-zigbee2mqtt-bridge-tlsat/mqtt-tlsin all three containers. Z2M getsZIGBEE2MQTT_CONFIG_MQTT_{SERVER,CA,CERT,KEY}by env. The init container no longer rendersmqtt_password. No container readsmosquitto-zigbee2mqtt-credentialsany more.zigbee2mqtt-discovery-guard.sh,zigbee2mqtt-interview-watch.sh:--cafile/--cert/--keyinstead of-u/-P; port 8884.zigbee2mqtt-config.yaml(seed only) andzigbee2mqtt-ws90-reporting.md: same settings, so a fresh PVC and the runbook match.Why env:
configuration.yamlon the PVC belongs to Z2M and is never re-seeded, so a template change would do nothing. Z2M 2.14.2 (lib/util/settings.tsapplyEnvironmentVariables) applies the env over the file. The file keepsuser: zigbee2mqttwith no password (!secret mqtt_passwordresolves to nothing). The broker ignores the username and takes the CN.Not here: the legacy user
zigbee2mqttstays in the broker's passwd/acl. Removing it needs a broker roll, which I batch with evcc/HA later.Outage merge: NO (one non-HA pod restarts)
Z2M restarts (
Recreate). Zigbee entities are unavailable for about 1–2 min while Z2M starts. HA does not restart. Z2M republishes all discovery configs fromstart(). HA-impact review by Hestia requested on the card (REN-953).How verified
kustomize build kubernetes/apps/home-assistantpasses;busybox sh -npasses for both scripts.use_identity_as_username, and a legacy passwd userzigbee2mqtt:zigbee2mqtt-bridgelogs in asu'zigbee2mqtt-bridge'with no username, with-u zigbee2mqtt, and with a wrong or legacy password. So Z2M's leftoveruser: zigbee2mqttis harmless.write homeassistant/#is allowed. Readinghomeassistant/#delivers nothing (ACL as before).zigbee2mqtt-discovery-guard.shruns over mTLS: it detectsbridge/groupsmissing while online, publishesbridge/request/restart(received), and the cooldown holds.mosquitto_publine deliversbridge/request/device/interview.After merge (I check)
Z2M pod Ready with 0 restarts; the broker log shows
u'zigbee2mqtt-bridge'and no newu'zigbee2mqtt'logins; 197 distincthomeassistant/*/configrepublished; guard and interview-watch logs without connect errors.Revert
Not a plain
git revert. Z2M copies env values intoconfiguration.yamlon its next settings write. Rollback PR: keep #1164, restoreMQTT_PASSWORDandmqtt_passwordin the init container, setZIGBEE2MQTT_CONFIG_MQTT_SERVER=mqtt://mosquitto:1883, and keep CA/CERT/KEY (the files exist; plainmqtt://does not use them). Revert the two scripts. The legacy user is still on the broker, so the password works at once.🤖 Generated with Claude Code
HA-impact review (Hestia, REN-968)
Impact: no HA restart, no outage merge. Zigbee is down briefly (Z2M
Recreate, ~1–2 min). HA, the broker and HA's own MQTT login do not change. Base topic, discovery topic and entity IDs stay the same, so automations and dashboards are not affected. While Z2M restarts, all Zigbee entities gounavailablethrough thebridge/stateLWT and come back after Z2M republishes discovery instart().Checked against branch
5be1d0a:mosquitto-mtlsserver cert has SANmosquitto, so the Z2M (mqtt.js,reject_unauthorizeddefault) andmosquitto_sub/pubhostname checks pass without--insecure.mosquitto-config.yaml, and themosquittoService and the container expose it.default-deny-ingressallows all traffic inside the namespace.zigbee2mqttuser, including the deliberate asymmetry onhomeassistant/#(write yes, read onlyhomeassistant/status).Merge condition: #1164 is merged and live first. This branch also contains the #1164 commits. With
Recreate, the old pod is gone before the new one can start. If Secretmqtt-zigbee2mqtt-bridge-tlsor the Dynamic Security client is missing, the new pod hangs inContainerCreatingor cannot log in. Every Zigbee light and switch then stays down until that is fixed. Before you merge, check inhome-assistant:mqtt-zigbee2mqtt-bridge-tlsexists and hasca.crt,tls.crtandtls.key.zigbee2mqtt-bridgecreated.After merge (HA side):
integration_entities('mqtt')= 423, of which 1 isunavailable;binary_sensor.zigbee2mqtt_bridge_connection_state= on. After the merge this should read the same within about 5 min.mqttorzigbee2mqtterrors.zigbee2mqtt-discovery-lost-on-mosquitto-restart. The discovery-guard repairs this within 5 min only if it can log in itself.Rollback: as in the PR description. A rollback PR, not a plain revert, because the env values are copied into
configuration.yaml.Go, once #1164 is live and the Secret plus the Dynamic Security client are confirmed. Merge at any time, no window needed.
Argus review at
5be1d0a2: APPROVED. Merge gated on #1164 merged and live (REN-969).Checked:
What breaks: if the Secret or the DynSec client is missing, Z2M sits in ContainerCreating or cannot log in, so all Zigbee devices are down. Who notices: the household right away, plus the Z2M readiness probe. Undo: rollback PR as described (password env + mqtt://:1883; the legacy user is still on the broker), takes minutes. Not an outage merge.
Before merging: Secret has ca.crt/tls.crt/tls.key; the zigbee2mqtt-bridge DynSec client exists.