66eb81b5e0
The *arr UIs behind arrproxy prompt "Authentication Required" because Sonarr v4 refuses remote access when AuthenticationMethod=None. Since arrproxy + oauth2-proxy already authenticate every user at the front door, the *arr apps should defer UI auth to the proxy instead of double-prompting. Extend the existing apikey-init container for sonarr/radarr/prowlarr to also idempotently enforce <AuthenticationMethod>External</AuthenticationMethod> and <AuthenticationRequired>Enabled</AuthenticationRequired> in /config/config.xml (create or replace, without disturbing ApiKey/UrlBase). In Servarr v4 External registers the same NoAuthenticationHandler as None (no username header required) but is exempt from the None remote-access block, so it stops the UI login prompt without needing arrproxy to forward any identity header (arrproxy's trustBoundary strips those by design).
149 lines
5.6 KiB
YAML
149 lines
5.6 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>, <UrlBase>, and
|
|
# <AuthenticationMethod>=External + <AuthenticationRequired>. External makes
|
|
# the *arr defer UI login to arrproxy/oauth2-proxy (same no-auth request
|
|
# handler as None, but permits remote access without prompting).
|
|
- 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
|
|
AUTH_METHOD=External
|
|
AUTH_REQUIRED=Enabled
|
|
CFG=/config/config.xml
|
|
if [ ! -f "$CFG" ]; then
|
|
printf '<Config>\n <ApiKey>%s</ApiKey>\n <UrlBase>%s</UrlBase>\n <AuthenticationMethod>%s</AuthenticationMethod>\n <AuthenticationRequired>%s</AuthenticationRequired>\n</Config>\n' "$API_KEY" "$URL_BASE" "$AUTH_METHOD" "$AUTH_REQUIRED" > "$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
|
|
if grep -q '<AuthenticationMethod>' "$CFG"; then
|
|
sed -i "s|<AuthenticationMethod>[^<]*</AuthenticationMethod>|<AuthenticationMethod>${AUTH_METHOD}</AuthenticationMethod>|" "$CFG"
|
|
else
|
|
sed -i "s|<Config>|<Config>\n <AuthenticationMethod>${AUTH_METHOD}</AuthenticationMethod>|" "$CFG"
|
|
fi
|
|
if grep -q '<AuthenticationRequired>' "$CFG"; then
|
|
sed -i "s|<AuthenticationRequired>[^<]*</AuthenticationRequired>|<AuthenticationRequired>${AUTH_REQUIRED}</AuthenticationRequired>|" "$CFG"
|
|
else
|
|
sed -i "s|<Config>|<Config>\n <AuthenticationRequired>${AUTH_REQUIRED}</AuthenticationRequired>|" "$CFG"
|
|
fi
|
|
fi
|
|
chown 1000:1000 "$CFG"
|
|
chmod 600 "$CFG"
|
|
echo "config-init: <ApiKey>, <UrlBase>=${URL_BASE}, <AuthenticationMethod>=${AUTH_METHOD}, <AuthenticationRequired>=${AUTH_REQUIRED} 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
|