Expose Zigbee2MQTT frontend via Authentik gate (zigbee2mqtt.home.renner.uno) #374

Merged
k.renner merged 1 commits from claude-bot/zigbee2mqtt-ingress into master 2026-07-23 13:08:49 +00:00
Member

Exposes the Z2M web UI behind the same passkey-gated Authentik proxy-outpost pattern as esphome/shelly-manager/vscode. The frontend has no auth of its own, so Traefik only routes the hostname to a dedicated outpost that validates the session first.

New files

  • apps/home-assistant/zigbee2mqtt-gate-service.yaml — ExternalName → ak-outpost-zigbee2mqtt-gate (authentik ns, :9000)
  • apps/home-assistant/zigbee2mqtt-ingress.yaml — zigbee2mqtt.home.renner.uno → outpost; zigbee2mqtt-tls auto-issued by cert-manager
  • apps/authentik/zigbee2mqtt-gate-egress.yaml — CNP: outpost → app.kubernetes.io/name: zigbee2mqtt on :8080

Edits

  • apps/authentik/blueprints-configmap.yaml — 5-entry blueprint block (group / proxy provider / application / policy binding / outpost) named zigbee2mqtt-gate. internal_host includes the explicit :8080 (Service listens on 8080, not esphome's :80). Authentik spawns the ak-outpost-zigbee2mqtt-gate Deployment+Service from this.
  • infrastructure/network-policies/home-assistant-ns.yaml — fromEndpoints rule admitting the outpost to :8080. Note: shared :8080 with vscode/shelly-manager — the fromEndpoints selector + the authentik-side egress scope it to the zigbee2mqtt pod.
  • both kustomizations register the new files.

Automatic / no action

DNS (k8s-gateway watches Ingress → creates the record), TLS (cert-manager ingress-shim). Access limited to the Zigbee2MQTT Managers group (k.renner).

Verified

kubectl kustomize builds all 3 dirs; --dry-run=server clean; the embedded blueprint YAML parses with the new 5-entry block.

After merge: Authentik reconciles the blueprint (~minutes) and spawns the outpost; then https://zigbee2mqtt.home.renner.uno prompts the passkey step-up and proxies the frontend.

🤖 Generated with Claude Code

Exposes the Z2M web UI behind the same passkey-gated Authentik proxy-outpost pattern as `esphome`/`shelly-manager`/`vscode`. The frontend has no auth of its own, so Traefik only routes the hostname to a dedicated outpost that validates the session first. ## New files - `apps/home-assistant/zigbee2mqtt-gate-service.yaml` — ExternalName → `ak-outpost-zigbee2mqtt-gate` (authentik ns, :9000) - `apps/home-assistant/zigbee2mqtt-ingress.yaml` — `zigbee2mqtt.home.renner.uno` → outpost; `zigbee2mqtt-tls` auto-issued by cert-manager - `apps/authentik/zigbee2mqtt-gate-egress.yaml` — CNP: outpost → `app.kubernetes.io/name: zigbee2mqtt` on :8080 ## Edits - `apps/authentik/blueprints-configmap.yaml` — 5-entry blueprint block (group / proxy provider / application / policy binding / outpost) named `zigbee2mqtt-gate`. `internal_host` includes the explicit **:8080** (Service listens on 8080, not esphome's :80). Authentik spawns the `ak-outpost-zigbee2mqtt-gate` Deployment+Service from this. - `infrastructure/network-policies/home-assistant-ns.yaml` — `fromEndpoints` rule admitting the outpost to :8080. **Note:** shared :8080 with vscode/shelly-manager — the `fromEndpoints` selector + the authentik-side egress scope it to the zigbee2mqtt pod. - both kustomizations register the new files. ## Automatic / no action DNS (`k8s-gateway` watches Ingress → creates the record), TLS (cert-manager ingress-shim). Access limited to the **Zigbee2MQTT Managers** group (`k.renner`). ## Verified `kubectl kustomize` builds all 3 dirs; `--dry-run=server` clean; the embedded blueprint YAML parses with the new 5-entry block. After merge: Authentik reconciles the blueprint (~minutes) and spawns the outpost; then `https://zigbee2mqtt.home.renner.uno` prompts the passkey step-up and proxies the frontend. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-07-23 13:03:58 +00:00
Expose Zigbee2MQTT frontend via Authentik gate
ci/woodpecker/pr/pr-review Pipeline was successful
de402ba531
Gate zigbee2mqtt.home.renner.uno behind the same passkey-step-up Authentik
proxy-outpost pattern used for esphome/shelly-manager/vscode. The Z2M frontend
has no auth of its own (anyone on :8080 controls the whole Zigbee network), so
Traefik only ever routes the hostname to a dedicated outpost that validates the
session before forwarding.

New:
  - apps/home-assistant/zigbee2mqtt-gate-service.yaml — ExternalName mirror to
    ak-outpost-zigbee2mqtt-gate in the authentik ns (:9000).
  - apps/home-assistant/zigbee2mqtt-ingress.yaml — zigbee2mqtt.home.renner.uno →
    the outpost; cert-manager ingress-shim issues zigbee2mqtt-tls.
  - apps/authentik/zigbee2mqtt-gate-egress.yaml — CNP letting the outpost egress
    to the zigbee2mqtt pod on :8080.

Edited:
  - apps/authentik/blueprints-configmap.yaml — 5-entry blueprint block (group /
    proxyprovider / application / policybinding / outpost) named zigbee2mqtt-gate;
    internal_host carries the explicit :8080 (Service listens on 8080, unlike
    esphome's :80). Authentik spawns the ak-outpost-zigbee2mqtt-gate Deployment
    +Service from the outpost entry.
  - infrastructure/network-policies/home-assistant-ns.yaml — fromEndpoints rule
    admitting the zigbee2mqtt-gate outpost to :8080 (shared 8080 with vscode/
    shelly-manager; the fromEndpoints selector + the authentik-side egress scope
    it to the zigbee2mqtt pod).
  - the two kustomizations registering the new files.

DNS (k8s-gateway watches Ingress) and TLS (cert-manager) are automatic. Access
limited to the "Zigbee2MQTT Managers" group (k.renner). Verified: kustomize
builds, dry-run OK, blueprint YAML parses with the new block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-opus-4-8 (complexity: complex), commit de402ba531ffe2e34f213e89f3344b730e689acf.

Advisory review by the review-bot pipeline. It never approves; a human merges. Push new commits to get a fresh review.


Summary

This PR exposes the Zigbee2MQTT frontend at zigbee2mqtt.home.renner.uno behind
a dedicated Authentik proxy-outpost, faithfully reproducing the existing
esphome-gate / shelly-manager-gate / vscode-gate pattern (ExternalName
mirror Service → outpost, Ingress, blueprint block, and paired Cilium
ingress/egress rules). I cross-checked every changed file against the
established patterns and the live Z2M Deployment/Service, and it is correct and
internally consistent. No blocking issues.

🟡 Suggestions

  • Shared :8080 blast radius (documented, but worth flagging). The new
    fromEndpoints grant in home-assistant-ns.yaml:84-91 sits on the
    endpointSelector: {} default-deny, so it admits the zigbee2mqtt-gate
    outpost to every :8080 pod in the namespace — that now includes
    code-server and shelly-manager, not just Z2M. The real scoping lives on the
    authentik side in zigbee2mqtt-gate-egress.yaml:14-22, which correctly
    restricts egress to app.kubernetes.io/name: zigbee2mqtt. This is the same
    acknowledged trade-off the file already carries for vscode/shelly, and the
    comment explains it well, so nothing is wrong — but the security guarantee
    rests entirely on the egress CNP staying in place. If you ever want
    defense-in-depth, the ingress side could be tightened with an
    app.kubernetes.io/name: zigbee2mqtt selector on a dedicated
    (non-{}) policy, the way home-assistant-rotator-ingress does at
    home-assistant-ns.yaml:356-373. Optional.

  • Outpost → Z2M :8080 reachability depends on the baseline authentik CNP for
    DNS/authentik-server egress.
    zigbee2mqtt-gate-egress.yaml only adds the
    home-assistant :8080 egress rule (mirroring esphome), relying on a baseline
    authentik-namespace policy to permit DNS resolution of
    zigbee2mqtt.home-assistant.svc.cluster.local and the callback to
    authentik-server. Since the identical esphome outpost works with this exact
    shape, this is almost certainly fine — noting it only as the one thing to
    confirm if the outpost 302-loops or can't resolve its internal_host
    post-deploy.

🟢 Nits

  • internal_host correctly carries the explicit :8080
    (blueprints-configmap.yaml:45) — matching the Z2M Service port
    (zigbee2mqtt-service.yaml:11), unlike esphome's implicit :80. The inline
    comment already calls this out; good catch by the author, since dropping the
    port would have silently sent the outpost to :80 and failed.

Tests

No automated tests accompany this change, which is consistent with the rest of
this GitOps repo (declarative Kubernetes manifests; no test harness in-tree).
The PR body states kubectl kustomize builds all three dirs and
--dry-run=server is clean. The meaningful verification here is runtime and
manual: after Authentik reconciles the blueprint, confirm (1) the
ak-outpost-zigbee2mqtt-gate Deployment/Service spawn in the authentik ns,
(2) https://zigbee2mqtt.home.renner.uno prompts the passkey step-up and
proxies the frontend, and (3) the live-state websocket survives the gate (the
credentials:'omit' service-worker 302-loop failure mode the author already
notes at blueprints-configmap.yaml:52-57).

Recommendation

Looks reasonable — no blocking issues; comments above are optional.

🤖 **Automated review** — model `claude-opus-4-8` (complexity: complex), commit `de402ba531ffe2e34f213e89f3344b730e689acf`. > Advisory review by the `review-bot` pipeline. It never approves; a human merges. Push new commits to get a fresh review. --- ## Summary This PR exposes the Zigbee2MQTT frontend at `zigbee2mqtt.home.renner.uno` behind a dedicated Authentik proxy-outpost, faithfully reproducing the existing `esphome-gate` / `shelly-manager-gate` / `vscode-gate` pattern (ExternalName mirror Service → outpost, Ingress, blueprint block, and paired Cilium ingress/egress rules). I cross-checked every changed file against the established patterns and the live Z2M Deployment/Service, and it is correct and internally consistent. No blocking issues. ## 🟡 Suggestions - **Shared `:8080` blast radius (documented, but worth flagging).** The new `fromEndpoints` grant in `home-assistant-ns.yaml:84-91` sits on the `endpointSelector: {}` default-deny, so it admits the `zigbee2mqtt-gate` outpost to *every* `:8080` pod in the namespace — that now includes code-server and shelly-manager, not just Z2M. The real scoping lives on the authentik side in `zigbee2mqtt-gate-egress.yaml:14-22`, which correctly restricts egress to `app.kubernetes.io/name: zigbee2mqtt`. This is the same acknowledged trade-off the file already carries for vscode/shelly, and the comment explains it well, so nothing is *wrong* — but the security guarantee rests entirely on the egress CNP staying in place. If you ever want defense-in-depth, the ingress side could be tightened with an `app.kubernetes.io/name: zigbee2mqtt` selector on a dedicated (non-`{}`) policy, the way `home-assistant-rotator-ingress` does at `home-assistant-ns.yaml:356-373`. Optional. - **Outpost → Z2M `:8080` reachability depends on the baseline authentik CNP for DNS/authentik-server egress.** `zigbee2mqtt-gate-egress.yaml` only adds the home-assistant `:8080` egress rule (mirroring esphome), relying on a baseline authentik-namespace policy to permit DNS resolution of `zigbee2mqtt.home-assistant.svc.cluster.local` and the callback to `authentik-server`. Since the identical esphome outpost works with this exact shape, this is almost certainly fine — noting it only as the one thing to confirm if the outpost 302-loops or can't resolve its `internal_host` post-deploy. ## 🟢 Nits - `internal_host` correctly carries the explicit `:8080` (`blueprints-configmap.yaml:45`) — matching the Z2M Service port (`zigbee2mqtt-service.yaml:11`), unlike esphome's implicit `:80`. The inline comment already calls this out; good catch by the author, since dropping the port would have silently sent the outpost to `:80` and failed. ## Tests No automated tests accompany this change, which is consistent with the rest of this GitOps repo (declarative Kubernetes manifests; no test harness in-tree). The PR body states `kubectl kustomize` builds all three dirs and `--dry-run=server` is clean. The meaningful verification here is runtime and manual: after Authentik reconciles the blueprint, confirm (1) the `ak-outpost-zigbee2mqtt-gate` Deployment/Service spawn in the authentik ns, (2) `https://zigbee2mqtt.home.renner.uno` prompts the passkey step-up and proxies the frontend, and (3) the live-state websocket survives the gate (the `credentials:'omit'` service-worker 302-loop failure mode the author already notes at `blueprints-configmap.yaml:52-57`). ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=de402ba531ffe2e34f213e89f3344b730e689acf -->
k.renner merged commit 211f1314ba into master 2026-07-23 13:08:49 +00:00
Sign in to join this conversation.