--- apiVersion: apps/v1 kind: Deployment metadata: name: arrproxy-api namespace: arrstack annotations: # Wave 2: start only after the wave-0 CNPG Cluster and VSO-synced Secrets # exist. The api self-migrates at startup under a Postgres advisory lock and # holds /readyz until the schema is current, so no migration ordering is needed. argocd.argoproj.io/sync-wave: "2" secret.reloader.stakater.com/reload: "arrproxy-pepper,arrproxy-admin-token,arrproxy-db-app,sonarr-adult-apikey,radarr-adult-apikey,sonarr-kids-apikey,radarr-kids-apikey" configmap.reloader.stakater.com/reload: "arrproxy-tiers" spec: replicas: 2 selector: matchLabels: app: arrproxy-api strategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate template: metadata: labels: app: arrproxy-api spec: serviceAccountName: default automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 seccompProfile: type: RuntimeDefault containers: - name: api image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/arrproxy-api:v0.6.0 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: http protocol: TCP env: - name: ARRPROXY_ADDR value: ":8080" # oauth2-proxy --pass-user-headers forwards identity to the upstream as # X-Forwarded-{User,Email,Groups} (a single comma-joined Groups value). # Email/User already match the api defaults; override the groups header # (default X-Auth-Request-Groups is auth_request-response-only and never # reaches this upstream) so group-based authorization works. - name: ARRPROXY_GROUPS_HEADER value: X-Forwarded-Groups # Real per-app *arr keys, projected one file per app under a per-tier # subdir (/) matching the tiers file: adult/{sonarr,radarr} # and kids/{sonarr,radarr}. Sourced from the same -apikey # Secrets the *arr Deployments consume. The api injects them server-side # and redacts them from every proxied response. - name: ARRPROXY_KEYS_DIR value: /etc/arrproxy/keys # Tier topology (fafflix/cheeztv): upstreams, route hashes, key subdirs # and group grants. Legacy unprefixed routes are retired in the file # (legacyRoutes:false); see arrproxy-tiers ConfigMap. - name: ARRPROXY_TIERS_FILE value: /etc/arrproxy/tiers/tiers.json - name: ARRPROXY_PEPPER valueFrom: secretKeyRef: name: arrproxy-pepper key: pepper # Machine-mint admin bearer, synced from Vault KV via the # arrproxy-admin-token VSO. Gates the /api/admin/ route that # oauth2-proxy intentionally skip-auths so OpenBao on the VMs can # mint tokens against arrproxy's own bearer. - name: ARRPROXY_ADMIN_TOKEN valueFrom: secretKeyRef: name: arrproxy-admin-token key: token # DSN assembled from the CNPG-generated arrproxy-db-app Secret; # $(VAR) expansion resolves the two env entries defined above it. - name: ARRPROXY_DB_USER valueFrom: secretKeyRef: name: arrproxy-db-app key: username - name: ARRPROXY_DB_PASSWORD valueFrom: secretKeyRef: name: arrproxy-db-app key: password - name: DATABASE_URL value: "postgres://$(ARRPROXY_DB_USER):$(ARRPROXY_DB_PASSWORD)@arrproxy-db-rw.arrstack.svc.cluster.local:5432/arrproxy?sslmode=require" volumeMounts: - name: arr-keys mountPath: /etc/arrproxy/keys readOnly: true - name: tiers mountPath: /etc/arrproxy/tiers readOnly: true - name: tmp mountPath: /tmp livenessProbe: httpGet: path: /livez port: http initialDelaySeconds: 10 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /readyz port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL resources: requests: cpu: 100m memory: 128Mi limits: cpu: "1" memory: 512Mi volumes: # Real per-tier *arr API keys, projected as / so the api # reads /etc/arrproxy/keys/{adult,kids}/{sonarr,radarr} (matching the # tiers file keyDir). Reuses the same -apikey Secrets the *arr # Deployments already consume (seeded by their VaultStaticSecrets). - name: arr-keys projected: sources: - secret: name: sonarr-adult-apikey items: - key: apitoken path: adult/sonarr - secret: name: radarr-adult-apikey items: - key: apitoken path: adult/radarr - secret: name: sonarr-kids-apikey items: - key: apitoken path: kids/sonarr - secret: name: radarr-kids-apikey items: - key: apitoken path: kids/radarr # Tier topology JSON (ARRPROXY_TIERS_FILE). - name: tiers configMap: name: arrproxy-tiers - name: tmp emptyDir: sizeLimit: 64Mi restartPolicy: Always