76da30d2f7
## Why arrproxy forwards `arrstack.unkin.net/<app>/...` to each *arr Service **preserving** the `/<app>` prefix. Without a matching `<UrlBase>` the apps 307-redirect to `/`, breaking path-based hosting. Prerequisite for arrproxy path routing (PR #377... arrproxy service account added in #376). ## Change Extend the existing idempotent `apikey-init` init container in sonarr/radarr/prowlarr to also enforce `<UrlBase>/<app></UrlBase>` in `/config/config.xml` (sonarr=/sonarr, radarr=/radarr, prowlarr=/prowlarr): - Set/replace `<UrlBase>` if present, insert after `<Config>` if absent, or write both `<ApiKey>` + `<UrlBase>` when creating a fresh config. `<ApiKey>` handling is unchanged. - Because Servarr moves all routes (including `/ping`) under the URL base, update liveness/readiness probes from `/ping` to `/<app>/ping` so they don't 404 once UrlBase is set. nzbget is not fronted by arrproxy and is left untouched. ## Validation - `kustomize build --enable-helm apps/overlays/au-syd1/arrstack` succeeds - `pre-commit` (yamllint etc.) passes --------- Co-authored-by: BenVincent <benvin@main.unkin.net> Co-authored-by: unkin-agent <unkin-agent@git.unkin.net> Reviewed-on: #378 Co-authored-by: Unkin Agent <unkin-agent@unkin.net> Co-committed-by: Unkin Agent <unkin-agent@unkin.net>
134 lines
4.4 KiB
YAML
134 lines
4.4 KiB
YAML
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: sonarr
|
|
namespace: arrstack
|
|
spec:
|
|
replicas: 1
|
|
strategy:
|
|
# RWO config PVC + single stateful SQLite DB: never run two pods at once.
|
|
type: Recreate
|
|
selector:
|
|
matchLabels:
|
|
app: sonarr
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: sonarr
|
|
spec:
|
|
securityContext:
|
|
# LinuxServer images init as root via s6 then step down to PUID/PGID.
|
|
# fsGroup makes the shared CephFS group-writable for that user;
|
|
# OnRootMismatch avoids a recursive chown of the whole media tree.
|
|
fsGroup: 1000
|
|
fsGroupChangePolicy: OnRootMismatch
|
|
initContainers:
|
|
# Enforce the Vault-sourced API key and the reverse-proxy URL base in
|
|
# /config/config.xml before the app starts. Vault is source of truth
|
|
# (override bootstrap): the key is minted in Vault, synced by VSO into the
|
|
# sonarr-apikey Secret, and written here. UrlBase=/sonarr lets arrproxy
|
|
# forward arrstack.unkin.net/sonarr/... with the prefix preserved (no 307).
|
|
# Runs as root to fix ownership; touches only <ApiKey> and <UrlBase>.
|
|
- name: apikey-init
|
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/busybox:1.37.0
|
|
imagePullPolicy: IfNotPresent
|
|
securityContext:
|
|
runAsUser: 0
|
|
env:
|
|
- name: API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: sonarr-apikey
|
|
key: apitoken
|
|
command:
|
|
- sh
|
|
- -c
|
|
- |
|
|
set -eu
|
|
case "$API_KEY" in
|
|
"" | *[!0-9a-fA-F]*)
|
|
echo "config-init: API_KEY missing or not hex; refusing" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
URL_BASE=/sonarr
|
|
CFG=/config/config.xml
|
|
if [ ! -f "$CFG" ]; then
|
|
printf '<Config>\n <ApiKey>%s</ApiKey>\n <UrlBase>%s</UrlBase>\n</Config>\n' "$API_KEY" "$URL_BASE" > "$CFG"
|
|
else
|
|
if grep -q '<ApiKey>' "$CFG"; then
|
|
sed -i "s|<ApiKey>[^<]*</ApiKey>|<ApiKey>${API_KEY}</ApiKey>|" "$CFG"
|
|
else
|
|
sed -i "s|<Config>|<Config>\n <ApiKey>${API_KEY}</ApiKey>|" "$CFG"
|
|
fi
|
|
if grep -q '<UrlBase>' "$CFG"; then
|
|
sed -i "s|<UrlBase>[^<]*</UrlBase>|<UrlBase>${URL_BASE}</UrlBase>|" "$CFG"
|
|
else
|
|
sed -i "s|<Config>|<Config>\n <UrlBase>${URL_BASE}</UrlBase>|" "$CFG"
|
|
fi
|
|
fi
|
|
chown 1000:1000 "$CFG"
|
|
chmod 600 "$CFG"
|
|
echo "config-init: <ApiKey> and <UrlBase>=${URL_BASE} enforced from Vault"
|
|
resources:
|
|
requests:
|
|
cpu: 50m
|
|
memory: 32Mi
|
|
limits:
|
|
cpu: 200m
|
|
memory: 64Mi
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /config
|
|
containers:
|
|
- name: sonarr
|
|
image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/linuxserver/sonarr:4.0.19
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: http
|
|
containerPort: 8989
|
|
protocol: TCP
|
|
env:
|
|
- name: PUID
|
|
value: "1000"
|
|
- name: PGID
|
|
value: "1000"
|
|
- name: TZ
|
|
value: Australia/Sydney
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /sonarr/ping
|
|
port: http
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /sonarr/ping
|
|
port: http
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /config
|
|
- name: media-tv
|
|
mountPath: /media/tv
|
|
volumes:
|
|
- name: config
|
|
persistentVolumeClaim:
|
|
claimName: sonarr-config
|
|
- name: media-tv
|
|
persistentVolumeClaim:
|
|
claimName: media-tv
|