mirror of
https://gitlab.kube.huskypup.net/Scooby/Homelabv4.git
synced 2026-08-21 05:26:49 +00:00
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>
215 lines
7.0 KiB
YAML
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
|