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.
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)
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>
🤖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 -->
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.
Part 1 of 2 for "Nabu", Home Assistant's Assist agent in Matrix. Part 2 is the Matrix integration and the automation in the
homeassistantrepo.Already set up outside git
@nabu:matrix.renner.uno(display name "Nabu"). Password login through MAS is verified (/loginok; the setup session was logged out again).#nabu:matrix.renner.uno(!nyjVYhak122oYyPp_2MZ3lUJQbCBOSSoo44Zf4R7Z2E) with @k.renner invited. HA's Matrix integration has no E2EE.apps/home-assistant/matrix(nabu_password), written by claude-bot, never displayed.In this PR
ha-matrix.render-matrix-password, an exact copy of therender-db-urlpattern: filter, append, shrink guard, 0600. It writesmatrix_nabu_passwordinto/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_passworddoesn't exist yet.Verified:
kubectl kustomize.🤖 Generated with Claude Code
🤖 Automated review — model
claude-opus-5-5, commitd16641661ce290e1d5f7352e9d91e484b2c6c5f1.Summary
The PR adds the
ha-matrixExternalSecret, which reads OpenBaoapps/home-assistant/matrix#nabu_password. It also adds an init container,render-matrix-password, that writes the value into/config/secrets.yamlasmatrix_nabu_passwordso the homeassistant repo can use!secretin part 2. I found no defects. The script is the existingrender-db-urlscript with only the key and env var changed. The base has not moved (maintip = base0911575), the PR is mergeable, and the only open PR that touches nearby files (#1344, Renovate) does not touchhome-assistant/deployment.yaml.⚪ Unverified
deployment.yaml:98relies on this, and:110puts 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 insecrets.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-read.hclgrants read onhomelab/data/*, andprometheus-token-externalsecret.yamlalready readsapps/home-assistant/...through the sameopenbaoClusterSecretStore, so access should work. I did not check the live policy or the store's namespace conditions.home-assistant-ns.yaml) allows Traefik, andmatrix-ns.yamlingress allows Traefik, so HA can reachmatrix.renner.uno. No network policy change looks needed, but I only read the policies; nothing was tested live.🟡 Suggestions
deployment.yaml:109-110). Therender-db-urlcomment (lines 49-54) gets away without escaping because CNPG limits its URI to a known character set. Nothing limits this password. One line before theprintfwould make the "hex" claim hold even after a manual re-seed of OpenBao, for examplecase "$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 brokensecrets.yaml.deployment.yaml:116-119). ThesecretKeyRefis required, so ifha-matrixis missing or fails to sync, the pod stays inCreateContainerConfigError. HA's startup now depends on a chat bot's credential, like it already does onha-pg-app. That trade-off may be fine, since part 2's!secretwould 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 forha-matrix, which is the right call given the restart cost described at lines 9-15.🟢 Nits
deployment.yaml:99-128copiesrender-db-urlline 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!secretkeys get added. Optional.Tests
This repo has no unit tests for manifests. CI (
ci-manifests-test.yml) and thekubectl kustomizerun mentioned in the PR body cover the rendering. The script is the same as the existingrender-db-urlapart from the key name. A pod restart in production is the real check: look formatrix_nabu_password renderedin the init container's logs and confirm the othersecrets.yamlkeys are still there.Recommendation
Looks reasonable — no blocking issues; comments above are optional.