# Authentik configuration authentik: secret_key: env://AUTHENTIK_SECRET_KEY postgresql: host: env://AUTHENTIK_POSTGRESQL__HOST port: 5432 name: env://AUTHENTIK_POSTGRESQL__NAME user: env://AUTHENTIK_POSTGRESQL__USER password: env://AUTHENTIK_POSTGRESQL__PASSWORD global: envFrom: # First secret: Authentik-specific settings (AUTHENTIK_SECRET_KEY) - secretRef: name: authentik # The second secretRef (pg-authentik-app, prefix: AUTHENTIK_POSTGRESQL__) # that used to live here is GONE - found live 2026-08-20 that it was # actively breaking things, not just redundant. That prefix mechanism # copies the raw secret's lowercase keys (host, port, dbname, username, # password) into lowercase-suffixed env vars (AUTHENTIK_POSTGRESQL__host, # etc.) - env var names are case-sensitive to Kubernetes, but authentik's # own generic AUTHENTIK_*-prefixed env-var scanner is NOT, and it was # picking up the lowercase AUTHENTIK_POSTGRESQL__host=pg-authentik-rw # instead of the explicit uppercase AUTHENTIK_POSTGRESQL__HOST override # below - silently connecting to the local CNPG service on port 5432 # the whole time regardless of what HOST/PORT were explicitly set to, # surfacing as an unexplained "connection timeout expired" loop (the # local hostname resolves fine in-cluster but on the VPS the request # apparently doesn't complete - never fully root-caused, just confirmed # dropping this duplicate source fixes it). Every key that secretRef # used to provide (dbname/username/password) is already explicitly set # via valueFrom below, so nothing is lost by removing it. env: # Configure external URL for proper OIDC discovery responses - name: AUTHENTIK_URL value: "https://auth.kube.huskypup.net" # Multi-site active failover pilot (see # /home/scooby/.claude/plans/jiggly-snacking-iverson.md): HOST/PORT # point at the floating pg-authentik.ha.huskypup.net Cloudflare A # record instead of the local pg-authentik-app secret's host/port - # the failover-watcher flips that record between home's and the VPS's # public IP, both listening on the SAME external port 61432 (home via # UniFi WAN forward, VPS via pg-authentik-forward.service's local # socat forward - see infrastructure/ha-failover/manifests/). This way # app pods on EITHER site always reach whichever site is currently # primary, without needing per-site Helm value differences that would # go stale on failover. # # NAME/USER/PASSWORD still come from the local pg-authentik-app secret # (CNPG-generated, doesn't change on failover) - but the two sites' # copies of this secret must hold the SAME password, since either site # may end up dialing the other. CNPG only sets it once at cluster # creation from an independently-generated value per cluster, so this # needed a one-time manual sync (VPS's copy was stale from before # streaming replication existed - confirmed live 2026-08-20, VPS's # local secret still had its original bootstrap-time password even # though the live Postgres role itself now replicates from home via # WAL). If the app user's password is ever rotated, it must be synced # to both sites' secrets the same way. - name: AUTHENTIK_POSTGRESQL__HOST value: "pg-authentik.ha.huskypup.net" - name: AUTHENTIK_POSTGRESQL__NAME valueFrom: secretKeyRef: name: pg-authentik-app key: dbname - name: AUTHENTIK_POSTGRESQL__USER valueFrom: secretKeyRef: name: pg-authentik-app key: username - name: AUTHENTIK_POSTGRESQL__PASSWORD valueFrom: secretKeyRef: name: pg-authentik-app key: password - name: AUTHENTIK_POSTGRESQL__PORT value: "61432" # Blueprints - Mount ConfigMaps for auto-discovery blueprints: configMaps: - authentik-blueprints-gitlab - authentik-blueprints-nextcloud - authentik-blueprints-argocd - authentik-blueprints-grafana - authentik-blueprints-forward-auth - authentik-blueprints-prometheus - authentik-blueprints-n8n - authentik-blueprints-ceph - authentik-blueprints-home-assistant - authentik-blueprints-guacamole - authentik-blueprints-percona-everest - authentik-blueprints-rancher - authentik-blueprints-netbird - authentik-blueprints-vault # Enable Prometheus metrics server: # Single replica required: the embedded outpost stores forward-auth sessions # in-memory (no Redis). Multiple replicas cause callback failures because # the session created during ext_authz check is only on one pod. replicas: 1 containerSecurityContext: runAsNonRoot: true allowPrivilegeEscalation: false capabilities: drop: - ALL seccompProfile: type: RuntimeDefault metrics: enabled: true serviceMonitor: enabled: true labels: release: prometheus # Resource limits to prevent OOM resources: requests: cpu: 50m memory: 512Mi limits: memory: 1Gi # Health probes - removed invalid 'enabled' fields startupProbe: initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 24 # 120 seconds for Authentik startup readinessProbe: initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 2 livenessProbe: initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 # Spread across nodes affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: authentik app.kubernetes.io/component: server topologyKey: kubernetes.io/hostname worker: containerSecurityContext: runAsNonRoot: true allowPrivilegeEscalation: false capabilities: drop: - ALL seccompProfile: type: RuntimeDefault metrics: enabled: true serviceMonitor: enabled: true labels: release: prometheus # Resource limits to prevent OOM resources: requests: cpu: 50m memory: 512Mi limits: memory: 1Gi # Spread across nodes affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: authentik app.kubernetes.io/component: worker topologyKey: kubernetes.io/hostname # Mount cert-manager secret for auto-import of Let's Encrypt cert volumeMounts: - name: certs mountPath: /certs readOnly: true volumes: - name: certs secret: secretName: authentik-tls optional: true # Disable bundled Postgres postgresql: enabled: false