2026-07-11 19:17:22 -07:00
|
|
|
# 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.
|
2026-07-19 09:29:17 -07:00
|
|
|
host: "https://authentik.riotpiao.com"
|
2026-07-11 19:17:22 -07:00
|
|
|
|
|
|
|
|
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
|
2026-07-20 23:40:08 -07:00
|
|
|
# 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.
|
2026-07-11 19:17:22 -07:00
|
|
|
|
|
|
|
|
_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;
|
2026-07-19 09:29:17 -07:00
|
|
|
# normal access is via nginx ingress (authentik.riotpiao.com → svc:80).
|
2026-07-11 19:17:22 -07:00
|
|
|
# Recreate: single replica + RWO-adjacent state — avoids split-brain on redeploy.
|
|
|
|
|
server:
|
|
|
|
|
replicas: 1
|
2026-07-20 22:55:23 -07:00
|
|
|
# Merge SOPS-CMP-emitted secret values after the chart's own `authentik` secret.
|
|
|
|
|
envFrom:
|
|
|
|
|
- secretRef:
|
|
|
|
|
name: authentik-secrets
|
2026-07-11 19:17:22 -07:00
|
|
|
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"
|
2026-07-21 22:31:48 -07:00
|
|
|
# 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
|
2026-07-11 19:17:22 -07:00
|
|
|
# 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
|
2026-07-21 11:08:23 -07:00
|
|
|
scrapeTimeout: 30s
|
2026-07-11 19:17:22 -07:00
|
|
|
|
|
|
|
|
# ── 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
|
2026-07-20 22:55:23 -07:00
|
|
|
envFrom:
|
|
|
|
|
- secretRef:
|
|
|
|
|
name: authentik-secrets
|
2026-07-11 19:17:22 -07:00
|
|
|
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
|
2026-07-21 11:08:23 -07:00
|
|
|
scrapeTimeout: 30s
|
2026-07-11 19:17:22 -07:00
|
|
|
|
|
|
|
|
# ── 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
|
|
|
|
|
|
2026-07-19 09:29:17 -07:00
|
|
|
# Ingress disabled — rule lives in k8s/ingress/ingress.yaml (authentik.riotpiao.com).
|
2026-07-11 19:17:22 -07:00
|
|
|
# For direct access during bootstrap: kubectl -n iam port-forward svc/authentik-server 7000:80
|