feat(home-assistant): render the Matrix bot password into secrets.yaml #1391

Merged
k.renner merged 1 commits from feat/ha-matrix-nabu-secret into main 2026-10-20 06:50:41 +00:00
Member

Part 1 of 2 for "Nabu", Home Assistant's Assist agent in Matrix. Part 2 is the Matrix integration and the automation in the homeassistant repo.

Already set up outside git

  • MAS account @nabu:matrix.renner.uno (display name "Nabu"). Password login through MAS is verified (/login ok; the setup session was logged out again).
  • Unencrypted room #nabu:matrix.renner.uno (!nyjVYhak122oYyPp_2MZ3lUJQbCBOSSoo44Zf4R7Z2E) with @k.renner invited. HA's Matrix integration has no E2EE.
  • Password in OpenBao at apps/home-assistant/matrix (nabu_password), written by claude-bot, never displayed.

In this PR

  • ExternalSecret ha-matrix.
  • Init container render-matrix-password, an exact copy of the render-db-url pattern: filter, append, shrink guard, 0600. It writes matrix_nabu_password into /config/secrets.yaml. HA only reads the password via !secret.

The deployment change restarts HA once. Merge this before the homeassistant PR, otherwise !secret matrix_nabu_password doesn't exist yet.

Verified: kubectl kustomize.

🤖 Generated with Claude Code

Part 1 of 2 for "Nabu", Home Assistant's Assist agent in Matrix. Part 2 is the Matrix integration and the automation in the `homeassistant` repo. ## Already set up outside git - MAS account `@nabu:matrix.renner.uno` (display name "Nabu"). Password login through MAS is verified (`/login` ok; the setup session was logged out again). - Unencrypted room `#nabu:matrix.renner.uno` (`!nyjVYhak122oYyPp_2MZ3lUJQbCBOSSoo44Zf4R7Z2E`) with @k.renner invited. HA's Matrix integration has no E2EE. - Password in OpenBao at `apps/home-assistant/matrix` (`nabu_password`), written by claude-bot, never displayed. ## In this PR - ExternalSecret `ha-matrix`. - Init container `render-matrix-password`, an exact copy of the `render-db-url` pattern: filter, append, shrink guard, 0600. It writes `matrix_nabu_password` into `/config/secrets.yaml`. HA only reads the password via `!secret`. The deployment change restarts HA once. Merge this **before** the homeassistant PR, otherwise `!secret matrix_nabu_password` doesn't exist yet. Verified: `kubectl kustomize`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
claude-bot added 1 commit 2026-10-20 06:47:27 +00:00
feat(home-assistant): render the Matrix bot password into secrets.yaml
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
d16641661c
Home Assistant's Matrix integration logs in as @nabu:matrix.renner.uno
(MAS account, password login verified) and only takes the password from
YAML, so it reaches HA the same way recorder_db_url does: OpenBao
apps/home-assistant/matrix -> ExternalSecret ha-matrix -> init container
render-matrix-password -> /config/secrets.yaml (matrix_nabu_password).
The config that uses it lands in the homeassistant repo.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review-bot left a comment
Member

🤖 Automated review — model claude-opus-5-5, commit d16641661ce290e1d5f7352e9d91e484b2c6c5f1.

Automated review by the review-bot: it approves only when it found nothing red or yellow, and a human still merges. Push new commits to get a fresh review.


Summary

The PR adds the ha-matrix ExternalSecret, which reads OpenBao apps/home-assistant/matrix#nabu_password. It also adds an init container, render-matrix-password, that writes the value into /config/secrets.yaml as matrix_nabu_password so the homeassistant repo can use !secret in part 2. I found no defects. The script is the existing render-db-url script with only the key and env var changed. The base has not moved (main tip = base 0911575), the PR is mergeable, and the only open PR that touches nearby files (#1344, Renovate) does not touch home-assistant/deployment.yaml.

⚪ Unverified

  • The OpenBao value is hex. deployment.yaml:98 relies on this, and :110 puts the value inside a double-quoted YAML string without escaping it. I can't read the secret, and nothing checks the value. A " or \ would produce invalid YAML in secrets.yaml. Whether that blocks only the Matrix integration or HA's whole config load depends on HA's loader, which I did not check.
  • ESO can read the path. eso-read.hcl grants read on homelab/data/*, and prometheus-token-externalsecret.yaml already reads apps/home-assistant/... through the same openbao ClusterSecretStore, so access should work. I did not check the live policy or the store's namespace conditions.
  • Network path for part 2. HA egress (home-assistant-ns.yaml) allows Traefik, and matrix-ns.yaml ingress allows Traefik, so HA can reach matrix.renner.uno. No network policy change looks needed, but I only read the policies; nothing was tested live.

🟡 Suggestions

  • Check the value before writing it (deployment.yaml:109-110). The render-db-url comment (lines 49-54) gets away without escaping because CNPG limits its URI to a known character set. Nothing limits this password. One line before the printf would make the "hex" claim hold even after a manual re-seed of OpenBao, for example case "$NABU_PASSWORD" in ''|*[!0-9a-fA-F]*) echo "FATAL: nabu_password not hex" >&2; exit 1;; esac. A clear init failure is easier to diagnose than a broken secrets.yaml.
  • HA now can't start without this secret (deployment.yaml:116-119). The secretKeyRef is required, so if ha-matrix is missing or fails to sync, the pod stays in CreateContainerConfigError. HA's startup now depends on a chat bot's credential, like it already does on ha-pg-app. That trade-off may be fine, since part 2's !secret would fail anyway without the key. If so, consider saying it in the comment at lines 96-98, as the recorder block does at lines 59-61. Also note that a change to the OpenBao value only reaches HA on the next pod restart: there is no Reloader annotation for ha-matrix, which is the right call given the restart cost described at lines 9-15.

🟢 Nits

  • deployment.yaml:99-128 copies render-db-url line for line. One init container that loops over key/env pairs would keep the filter, shrink-guard and chmod logic in one place as more !secret keys get added. Optional.

Tests

This repo has no unit tests for manifests. CI (ci-manifests-test.yml) and the kubectl kustomize run mentioned in the PR body cover the rendering. The script is the same as the existing render-db-url apart from the key name. A pod restart in production is the real check: look for matrix_nabu_password rendered in the init container's logs and confirm the other secrets.yaml keys are still there.

Recommendation

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

🤖 **Automated review** — model `claude-opus-5-5`, commit `d16641661ce290e1d5f7352e9d91e484b2c6c5f1`. > Automated review by the `review-bot`: it approves only when it found nothing red or yellow, and a human still merges. Push new commits to get a fresh review. --- ## Summary The PR adds the `ha-matrix` ExternalSecret, which reads OpenBao `apps/home-assistant/matrix#nabu_password`. It also adds an init container, `render-matrix-password`, that writes the value into `/config/secrets.yaml` as `matrix_nabu_password` so the homeassistant repo can use `!secret` in part 2. I found no defects. The script is the existing `render-db-url` script with only the key and env var changed. The base has not moved (`main` tip = base `0911575`), the PR is mergeable, and the only open PR that touches nearby files (#1344, Renovate) does not touch `home-assistant/deployment.yaml`. ## ⚪ Unverified - **The OpenBao value is hex.** `deployment.yaml:98` relies on this, and `:110` puts the value inside a double-quoted YAML string without escaping it. I can't read the secret, and nothing checks the value. A `"` or `\` would produce invalid YAML in `secrets.yaml`. Whether that blocks only the Matrix integration or HA's whole config load depends on HA's loader, which I did not check. - **ESO can read the path.** `eso-read.hcl` grants read on `homelab/data/*`, and `prometheus-token-externalsecret.yaml` already reads `apps/home-assistant/...` through the same `openbao` ClusterSecretStore, so access should work. I did not check the live policy or the store's namespace conditions. - **Network path for part 2.** HA egress (`home-assistant-ns.yaml`) allows Traefik, and `matrix-ns.yaml` ingress allows Traefik, so HA can reach `matrix.renner.uno`. No network policy change looks needed, but I only read the policies; nothing was tested live. ## 🟡 Suggestions - **Check the value before writing it** (`deployment.yaml:109-110`). The `render-db-url` comment (lines 49-54) gets away without escaping because CNPG limits its URI to a known character set. Nothing limits this password. One line before the `printf` would make the "hex" claim hold even after a manual re-seed of OpenBao, for example `case "$NABU_PASSWORD" in ''|*[!0-9a-fA-F]*) echo "FATAL: nabu_password not hex" >&2; exit 1;; esac`. A clear init failure is easier to diagnose than a broken `secrets.yaml`. - **HA now can't start without this secret** (`deployment.yaml:116-119`). The `secretKeyRef` is required, so if `ha-matrix` is missing or fails to sync, the pod stays in `CreateContainerConfigError`. HA's startup now depends on a chat bot's credential, like it already does on `ha-pg-app`. That trade-off may be fine, since part 2's `!secret` would fail anyway without the key. If so, consider saying it in the comment at lines 96-98, as the recorder block does at lines 59-61. Also note that a change to the OpenBao value only reaches HA on the next pod restart: there is no Reloader annotation for `ha-matrix`, which is the right call given the restart cost described at lines 9-15. ## 🟢 Nits - `deployment.yaml:99-128` copies `render-db-url` line for line. One init container that loops over key/env pairs would keep the filter, shrink-guard and chmod logic in one place as more `!secret` keys get added. Optional. ## Tests This repo has no unit tests for manifests. CI (`ci-manifests-test.yml`) and the `kubectl kustomize` run mentioned in the PR body cover the rendering. The script is the same as the existing `render-db-url` apart from the key name. A pod restart in production is the real check: look for `matrix_nabu_password rendered` in the init container's logs and confirm the other `secrets.yaml` keys are still there. ## Recommendation Looks reasonable — no blocking issues; comments above are optional. <!-- pr-review:sha=d16641661ce290e1d5f7352e9d91e484b2c6c5f1 -->
k.renner merged commit 63012f0dc6 into main 2026-10-20 06:50:41 +00:00
Sign in to join this conversation.