arrstack: manage sonarr/radarr/prowlarr API keys via Vault #369

Merged
benvin merged 1 commits from benvin/arrstack-vault-apikeys into main 2026-08-15 16:43:03 +10:00
Member

Why

The sonarr/radarr/prowlarr images self-generate an API key into
/config/config.xml on first boot, so the key is unmanaged and differs per
volume reset. This makes Vault the source of truth for those keys (override
bootstrap, chosen by Ben): the key is minted in Vault and enforced into
config.xml before each app starts.

Changes

  • Add a VaultAuth default in the arrstack namespace (kubernetes auth,
    mount k8s/au/syd1, role default, SA default), mirroring jellyfin.
  • Add a per-app VaultStaticSecret that syncs
    kv/kubernetes/namespace/arrstack/default/<app> (key apitoken) into the
    <app>-apikey Secret. The default k8s role's templated policy already
    grants read on that path for the arrstack/default SA, so no
    terraform-vault change is needed.
  • Add an apikey-init initContainer to each of the three deployments that
    reads API_KEY from the VSO-created Secret, fails closed on a missing or
    non-hex value, and writes/updates only the <ApiKey> element in
    /config/config.xml (then fixes ownership 1000:1000, mode 600). Image is a
    pinned busybox via artifactapi to keep this PR atomic (no new image
    dependency).
  • Wire the new manifests into the base and per-app kustomizations.

Notes

  • Keys already seeded in Vault at kv/kubernetes/namespace/arrstack/default/<app>.
  • nzbget is out of scope: it has no config.xml <ApiKey> (uses ControlPassword),
    a separate follow-up.
  • Downstream consumers (proxy, terraform) currently read
    kv/service/media-apps/<app>; the authoritative key now lives at the path
    above. Reconciliation is deferred.
## Why The sonarr/radarr/prowlarr images self-generate an API key into /config/config.xml on first boot, so the key is unmanaged and differs per volume reset. This makes Vault the source of truth for those keys (override bootstrap, chosen by Ben): the key is minted in Vault and enforced into config.xml before each app starts. ## Changes - Add a `VaultAuth` `default` in the `arrstack` namespace (kubernetes auth, mount `k8s/au/syd1`, role `default`, SA `default`), mirroring jellyfin. - Add a per-app `VaultStaticSecret` that syncs `kv/kubernetes/namespace/arrstack/default/<app>` (key `apitoken`) into the `<app>-apikey` Secret. The `default` k8s role's templated policy already grants read on that path for the `arrstack/default` SA, so no terraform-vault change is needed. - Add an `apikey-init` initContainer to each of the three deployments that reads `API_KEY` from the VSO-created Secret, fails closed on a missing or non-hex value, and writes/updates only the `<ApiKey>` element in `/config/config.xml` (then fixes ownership 1000:1000, mode 600). Image is a pinned busybox via artifactapi to keep this PR atomic (no new image dependency). - Wire the new manifests into the base and per-app kustomizations. ## Notes - Keys already seeded in Vault at `kv/kubernetes/namespace/arrstack/default/<app>`. - nzbget is out of scope: it has no config.xml `<ApiKey>` (uses ControlPassword), a separate follow-up. - Downstream consumers (proxy, terraform) currently read `kv/service/media-apps/<app>`; the authoritative key now lives at the path above. Reconciliation is deferred.
unkin-agent added 1 commit 2026-08-15 16:39:11 +10:00
arrstack: manage sonarr/radarr/prowlarr API keys via Vault
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful
0ddb57f687
Vault is the source of truth for the sonarr/radarr/prowlarr API keys
(override bootstrap): keys are minted in Vault and enforced into each
app's /config/config.xml on startup, replacing the images'
self-generated keys.

- add a VaultAuth 'default' in the arrstack namespace (k8s auth, mount
  k8s/au/syd1, role default, SA default) mirroring the jellyfin pattern
- add a per-app VaultStaticSecret syncing
  kv/kubernetes/namespace/arrstack/default/<app> (key apitoken) into the
  <app>-apikey Secret; the default k8s role's templated policy already
  grants read there, so no terraform-vault change is needed
- add an apikey-init initContainer to each deployment that fails closed
  on a missing/non-hex key and writes/updates only the <ApiKey> element
  in /config/config.xml (busybox via artifactapi, runs as root)
- wire the new manifests into the base and per-app kustomizations

nzbget is out of scope (no config.xml <ApiKey>; uses ControlPassword).
benvin merged commit d387301d6b into main 2026-08-15 16:43:03 +10:00
benvin deleted branch benvin/arrstack-vault-apikeys 2026-08-15 16:43:03 +10:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: unkin/argocd-apps#369