--- apiVersion: apps/v1 kind: Deployment metadata: name: radarr-adult namespace: arrstack annotations: # Reloader rolls the Deployment when radarr-adult-env changes (plain envFrom # ConfigMap does not trigger a rollout on its own). configmap.reloader.stakater.com/auto: "true" spec: # Active-active: the -unkin2 fork keeps all state in the shared Postgres # (arrstack-postgres) and coordinates via Postgres advisory locks, so N # replicas run concurrently behind the radarr-adult Service. RollingUpdate is # safe — no SQLite, no RWO lock. replicas: 3 strategy: type: RollingUpdate selector: matchLabels: app: radarr-adult template: metadata: labels: app: radarr-adult spec: securityContext: # Fork image has no USER; pin it to a non-root UID and group-write the # shared RWX CephFS media subtree. OnRootMismatch avoids a recursive # chown of the whole media tree. runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 fsGroupChangePolicy: OnRootMismatch initContainers: # Gate the app on its own Postgres database+role being reachable. # waitfordb reads the PG* env as a libpq fallback, so the password never # lands in argv. - name: wait-for-db image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/waitfordb:v0.1.0 env: - name: WAITFORDB_TIMEOUT value: 5m - name: WAITFORDB_SSLMODE value: disable - name: PGHOST value: arrstack-postgres-rw.arrstack.svc.cluster.local - name: PGPORT value: "5432" - name: PGDATABASE value: radarr-adult-main - name: PGUSER valueFrom: secretKeyRef: name: radarr-adult-db key: username - name: PGPASSWORD valueFrom: secretKeyRef: name: radarr-adult-db key: password resources: requests: cpu: 10m memory: 32Mi limits: cpu: 100m memory: 64Mi containers: - name: radarr image: artifactapi.k8s.syd1.au.unkin.net/docker-internal/radarr:v6.4.2-unkin7 imagePullPolicy: IfNotPresent command: - /app/Radarr args: - -nobrowser - -data=/config # Bypass the single-instance guard so multiple replicas can share one # /config. Cross-replica safety is the Postgres layer, not a lock file. - -nosingleinstancecheck ports: - name: http containerPort: 7878 protocol: TCP envFrom: - configMapRef: name: radarr-adult-env env: - name: Radarr__Postgres__User valueFrom: secretKeyRef: name: radarr-adult-db key: username - name: Radarr__Postgres__Password valueFrom: secretKeyRef: name: radarr-adult-db key: password - name: Radarr__Auth__ApiKey valueFrom: secretKeyRef: name: radarr-adult-apikey key: apitoken # MediaCover object store (shared arrstack-media Ceph RGW bucket, # partitioned by the radarr-adult key prefix). - name: Radarr__MediaCover__S3__Endpoint valueFrom: secretKeyRef: name: arrstack-media-s3 key: S3_ENDPOINT - name: Radarr__MediaCover__S3__AccessKey valueFrom: secretKeyRef: name: arrstack-media-s3 key: AWS_ACCESS_KEY_ID - name: Radarr__MediaCover__S3__SecretKey valueFrom: secretKeyRef: name: arrstack-media-s3 key: AWS_SECRET_ACCESS_KEY - name: Radarr__MediaCover__S3__Bucket value: arrstack-media - name: Radarr__MediaCover__S3__Prefix value: radarr-adult - name: Radarr__MediaCover__S3__ForcePathStyle value: "true" - name: Radarr__MediaCover__S3__CaCertPath value: /etc/ssl/vault-ca/ca.crt # Backup object store (shared arrstack-backups Ceph RGW bucket, # partitioned by the radarr-adult key prefix). - name: Radarr__BackupS3__Endpoint valueFrom: secretKeyRef: name: arrstack-backups-s3 key: S3_ENDPOINT - name: Radarr__BackupS3__AccessKey valueFrom: secretKeyRef: name: arrstack-backups-s3 key: AWS_ACCESS_KEY_ID - name: Radarr__BackupS3__SecretKey valueFrom: secretKeyRef: name: arrstack-backups-s3 key: AWS_SECRET_ACCESS_KEY - name: Radarr__BackupS3__Bucket value: arrstack-backups - name: Radarr__BackupS3__Prefix value: radarr-adult - name: Radarr__BackupS3__ForcePathStyle value: "true" - name: Radarr__BackupS3__CaCertPath value: /etc/ssl/vault-ca/ca.crt livenessProbe: httpGet: path: /3aa168/radarr/ping port: http initialDelaySeconds: 30 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /3aa168/radarr/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 # Adult movies subtree of the shared media-movies PVC (same CephFS # subvolume the kids radarr writes and jellyfin reads). - name: media-movies mountPath: /media/movies subPath: movies/adult - name: vault-ca mountPath: /etc/ssl/vault-ca readOnly: true # exportarr sidecar: polls the local replica's API and exposes Prometheus # metrics on :9708 (scraped by the radarr-adult-exportarr VMPodScrape). - name: exportarr image: ghcr.io/onedr0p/exportarr:v2.3.0 imagePullPolicy: IfNotPresent args: - radarr env: - name: PORT value: "9708" # URL includes the /3aa168/radarr UrlBase (Radarr__Server__UrlBase). - name: URL value: http://localhost:7878/3aa168/radarr - name: APIKEY valueFrom: secretKeyRef: name: radarr-adult-apikey key: apitoken ports: - name: metrics containerPort: 9708 protocol: TCP livenessProbe: httpGet: path: /healthz port: metrics initialDelaySeconds: 15 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: httpGet: path: /healthz port: metrics initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 resources: requests: cpu: 25m memory: 32Mi limits: cpu: 100m memory: 128Mi volumes: - name: config emptyDir: {} - name: media-movies persistentVolumeClaim: claimName: media-movies # Estate CA for validating the Ceph RGW (s3.ceph.unkin.net) TLS cert. - name: vault-ca secret: secretName: vault-ca-cert items: - key: ca.crt path: ca.crt