Files
Homelabv4/infrastructure/authentik/values.yaml
T
Scooby HuskyandClaude Sonnet 5 d9a4c16481 Move all 8 Authentik OIDC client_secrets out of plaintext git
Completes the 'make the repo proper' cleanup from earlier this session -
these were flagged but deliberately not touched in 185e9c2 given the
blast radius (live SSO for 8 apps). User confirmed: fix all 8 now.

infrastructure/authentik/{argocd,gitlab,nextcloud,grafana,n8n,guacamole,
rancher,vault}-blueprint.yaml: converted from plain ConfigMap (client_secret
hardcoded) to ExternalSecret with a templated blueprint body
(client_secret: "{{ .clientSecret }}") pulling from Vault. Chart already
supports mounting blueprints from Secrets (blueprints.secrets, alongside
blueprints.configMaps) - infrastructure/authentik/values.yaml updated to
route these 8 there instead.

For argocd/nextcloud/n8n/guacamole/rancher: Vault already had the matching
value at secret/<app>-oauth (the APP side was already Vault-backed via its
own ExternalSecret) - the blueprint was the only remaining plaintext copy.

For gitlab/grafana/vault: Vault had no copy at all yet - created
secret/{gitlab,grafana,vault}-oauth with the EXISTING live values (not
rotated - these are the actual working credentials right now, rotating
would break login until every consumer is updated in lockstep, which is
out of scope for a cleanup pass). Also fixed the OTHER plaintext copies
that existed for these three specifically:
  - apps/gitlab/manifests/external-secret-oidc.yaml (new): replaces a
    manually kubectl-created, never-git-tracked gitlab-oidc-secret.
  - infrastructure/grafana/manifests/grafana-oauth-secret.yaml: was a
    plain Secret whose own comment said 'hardcoded from blueprint'.
  - infrastructure/vault/manifests/vault-init-{configmap,job}.yaml: this
    one COULDN'T be converted to the same ExternalSecret-from-Vault
    pattern - it's the PostSync Job that grants ESO's own Kubernetes-auth
    role in Vault, so ESO can't yet authenticate to pull anything from
    Vault at the point this script runs (genuinely circular). Sourced
    from a new vault-oidc-bootstrap Secret instead - created once
    manually (kubectl, not git, matching how Vault's own root/unseal
    material is already handled), independent of the ESO pipeline.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-20 20:04:22 -05:00

215 lines
7.0 KiB
YAML

# 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 (no secrets) or
# Secrets (client_secret-bearing ones, ExternalSecret-templated from
# Vault - found and fixed 2026-08-20, see each file's own header for
# what it used to look like).
blueprints:
configMaps:
- authentik-blueprints-forward-auth
- authentik-blueprints-prometheus
- authentik-blueprints-ceph
- authentik-blueprints-home-assistant
- authentik-blueprints-percona-everest
- authentik-blueprints-netbird
secrets:
- authentik-blueprints-gitlab
- authentik-blueprints-nextcloud
- authentik-blueprints-argocd
- authentik-blueprints-grafana
- authentik-blueprints-n8n
- authentik-blueprints-guacamole
- authentik-blueprints-rancher
- 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