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).
## Why
Stands up the download-automation stack (sonarr, radarr, prowlarr, nzbget) in a new `arrstack` namespace, sharing the same CephFS TV/movies subvolumes that jellyfin serves read-only (jellyfin static-PV rework is on the base branch, PR #237). Downloads and libraries live on one filesystem per media type so the arrs import with atomic hardlink moves.
## Changes
- Add `apps/base/arrstack/` namespace with its own static CephFS PVs (`arrstack-media-tv`, `arrstack-media-movies`) + RWX PVCs (`media-tv`, `media-movies`) bound to the same rootPaths jellyfin uses; each namespace gets a unique PV name/volumeHandle pinned by claimRef.
- Deploy sonarr (mounts media-tv RW), radarr (media-movies RW), prowlarr (config only), nzbget (both media PVCs RW); single replica, Recreate strategy, LinuxServer images via artifactapi dockerhub remote, PUID/PGID/TZ, probes, fsGroup for CephFS writability.
- Per-app config PVCs on `cephrbd-fast-retain` (RWO, 5Gi) for the SQLite state; internal-only Gateway + HTTPRoute per app (traefik-internal, vault-issuer, external-dns `<app>.k8s.syd1.au.unkin.net`), no oauth yet.
- nzbget: initContainer seeds `/config/nzbget.conf` (copy image template if absent, append managed path/category block once) and creates the media dirs; category `tv` -> `/media/tv/downloads`, `movies` -> `/media/movies/downloads`.
- Wire ArgoCD: add `apps/overlays/*/arrstack` to the media ApplicationSet. (media AppProject already gains the arrstack destination + PersistentVolume whitelist on the base branch.)
## Depends on
terraform-artifactapi PR #31 (allowlist `^linuxserver/` on the dockerhub remote) must be merged + applied before these pods can pull.
## Follow-up (terraform)
Root folders (/media/tv/series, /media/movies/films), download-client wiring (host `nzbget`, port 6789, categories tv/movies) and API keys are configured later via terraform-arr.
---------
Co-authored-by: Ben Vincent <neotheo@gmail.com>
Co-authored-by: Ben Vin <neotheo@gmail.com>
Reviewed-on: #366
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>