# 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
  - name: authentik-migrate
    image: ghcr.io/goauthentik/server:2026.5.4
    imagePullPolicy: IfNotPresent
    command:
      - sh
      - -c
      - python -m manage migrate --noinput
    envFrom:
      - secretRef:
          name: authentik
    volumeMounts: *caVolumeMounts

_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
  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"
  # 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: 60s

# ── 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
  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: 60s

# ── 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
