# k8s/talos-iam/authentik-values.yaml # Authentik — SSO Identity Provider for the homelab. # Provides OAuth2/OIDC login for Grafana, MinIO, Forgejo, and Argo CD. # Chart: authentik/authentik from https://charts.goauthentik.io # # Architecture: server (UI+API) + worker (background tasks) + PostgreSQL + Redis. # PostgreSQL is the system of record — must persist. Redis is ephemeral cache/queue. # # Secrets injected via helmfile --set (from .env / vsource): # AUTHENTIK_SECRET_KEY — signs sessions and tokens; set once, never rotate casually # AUTHENTIK_BOOTSTRAP_PASSWORD — initial akadmin password (used once at first login) # AUTHENTIK_BOOTSTRAP_TOKEN — API token for the setup_talos_iam.sh bootstrap script # AUTHENTIK_PG_PASSWORD — PostgreSQL user password authentik: # host: the external URL Authentik uses to build redirect URIs in OAuth2 flows. # Must match what the browser sees — if it returns an internal svc URL, # the browser's redirect after login will fail (can't reach svc DNS externally). # HTTP (not HTTPS) because the Authentik ingress has no TLS cert configured. host: "https://authentik.riotpiao.com" error_reporting: enabled: false # do not phone home to Sentry # PostgreSQL connection — points at CloudNativePG cluster in ddb namespace. # password is injected via helmfile --set at deploy time. postgresql: host: ddb-cluster-rw.ddb.svc.cluster.local port: 5432 name: authentik user: authentik password: "" # injected via helmfile --set authentik.postgresql.password # Redis connection — bundled subchart, standalone mode (no sentinel/cluster). redis: host: authentik-redis-master # ── HTTP client timeouts ────────────────────────────────────────────────────── # Increased to tolerate 5+ second pod-to-pod network latency. # Affects webhooks, outpost management, SCIM, LDAP sync. # Default: ~30s — too aggressive when latency spikes hit 5-10s. log_level: debug # enable debug logging to monitor connection issues # ── CA trust (shared by server and worker) ──────────────────────────────────── # Authentik (Python/Debian) uses requests + httpx for outgoing HTTPS — webhooks, # outpost management, SCIM. Both libraries need REQUESTS_CA_BUNDLE / SSL_CERT_FILE # to point to a bundle that includes homelab-ca, otherwise connections to other # homelab services fail with "certificate signed by unknown authority". # # Strategy: a debian:12-slim init container (run as root) concatenates the # Debian system Mozilla bundle with homelab-ca.crt into an emptyDir. The main # container then references /merged/ca-bundle.crt via two env vars that cover # every Python HTTP library. _caVolumes: &caVolumes - name: homelab-ca configMap: name: homelab-ca - name: merged-ca emptyDir: {} _caVolumeMounts: &caVolumeMounts - name: homelab-ca mountPath: /homelab-ca readOnly: true - name: merged-ca mountPath: /merged readOnly: true _caInitContainers: &caInitContainers - name: merge-ca-certs image: debian:bookworm imagePullPolicy: IfNotPresent securityContext: runAsUser: 0 command: - sh - -c - (cat /etc/ssl/certs/ca-certificates.crt 2>/dev/null; cat /homelab-ca/homelab-ca.crt) > /merged/ca-bundle.crt volumeMounts: - name: homelab-ca mountPath: /homelab-ca readOnly: true - name: merged-ca mountPath: /merged # NOTE: no authentik-migrate init container — the authentik `server` entrypoint # runs migrations itself on startup. A separate `manage migrate` init pinned to # an older image tripped a version-history precheck on an empty DB # (relation "authentik_version_history" does not exist) and blocked boot. _caEnv: &caEnv - name: REQUESTS_CA_BUNDLE value: /merged/ca-bundle.crt - name: SSL_CERT_FILE value: /merged/ca-bundle.crt # ── Authentik server (UI + API) ─────────────────────────────────────────────── # Handles all browser traffic: login flows, admin UI, OAuth2 authorize/token endpoints. # NodePort 32172 is a fallback for direct node access during troubleshooting; # normal access is via nginx ingress (authentik.riotpiao.com → svc:80). # Recreate: single replica + RWO-adjacent state — avoids split-brain on redeploy. server: replicas: 1 # Merge SOPS-CMP-emitted secret values after the chart's own `authentik` secret. envFrom: - secretRef: name: authentik-secrets deploymentStrategy: type: Recreate service: type: NodePort nodePort: 32172 resources: requests: cpu: 100m memory: 512Mi limits: cpu: 1000m memory: 1Gi tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule volumes: *caVolumes volumeMounts: *caVolumeMounts initContainers: *caInitContainers env: *caEnv podAnnotations: configmap.reloader.stakater.com/reload: "homelab-ca" homelab.io/restart-at: "2026-06-21T13-40" # The /-/health/{live,ready}/ endpoints do a DB round-trip; under transient # CNPG contention they respond in 5-6s while still returning 200. The chart's # default 3s liveness timeout then flags a working backend as dead and kubelet # kills it in a restart loop — the pod never stays Ready, gets dropped from the # authentik-server Service endpoints, and the OAuth-provisioning PostSync hook # fails with "Host is unreachable". Widen the timeouts so slow-but-healthy # checks aren't treated as failures. (Only these fields are overridden; the # chart deep-merges the rest of each probe, incl. the httpGet path.) livenessProbe: timeoutSeconds: 15 failureThreshold: 6 readinessProbe: timeoutSeconds: 15 failureThreshold: 6 startupProbe: timeoutSeconds: 15 failureThreshold: 120 # 120 × 10s = 20min for fresh DB migrations # Every OIDC login (Grafana, Argo CD, MinIO, Forgejo) depends on this server — # its request latency/error rate explains SSO-driven slowness on those services. metrics: enabled: true serviceMonitor: enabled: true scrapeTimeout: 30s # ── Authentik worker ────────────────────────────────────────────────────────── # Runs background tasks: email delivery, LDAP sync, flow policy evaluation, # event log cleanup, and managed outpost updates. Stateless — no PVC needed. # Same resource profile as server; Authentik 2023+ merged some worker duties # into the server process but the worker pod is still required. worker: replicas: 1 envFrom: - secretRef: name: authentik-secrets deploymentStrategy: type: Recreate resources: requests: cpu: 100m memory: 512Mi limits: cpu: 1000m memory: 1Gi tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule volumes: *caVolumes volumeMounts: *caVolumeMounts initContainers: *caInitContainers env: *caEnv podAnnotations: configmap.reloader.stakater.com/reload: "homelab-ca" homelab.io/restart-at: "2026-06-21T13-40" metrics: enabled: true serviceMonitor: enabled: true scrapeTimeout: 30s # ── PostgreSQL (external: CloudNativePG cluster in ddb namespace) ───────────── # Authentik connects to the centralized ddb-cluster (1 primary + 2 replicas with pgvector). # Do not use the bundled Bitnami subchart — CNPG is already running. postgresql: enabled: false primary: persistence: enabled: true storageClass: longhorn size: 8Gi tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: node-role.kubernetes.io/worker operator: Exists # ── Bundled Redis ───────────────────────────────────────────────────────────── # Cache and async task queue only — no durable data. If Redis restarts, in-flight # background tasks are retried and cached tokens are recomputed. Losing Redis # data does not lose user accounts or flow configuration (that's in PostgreSQL). # persistence: false saves a PVC and makes restarts faster. # # Same prefer-worker / fallback-to-cp scheduling as PostgreSQL. # architecture: standalone — no Sentinel/cluster overhead for a 3-node homelab. redis: enabled: true master: persistence: enabled: false tolerations: - key: node-role.kubernetes.io/control-plane operator: Exists effect: NoSchedule affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 preference: matchExpressions: - key: node-role.kubernetes.io/worker operator: Exists architecture: standalone # Ingress disabled — rule lives in k8s/ingress/ingress.yaml (authentik.riotpiao.com). # For direct access during bootstrap: kubectl -n iam port-forward svc/authentik-server 7000:80