# Authentik — IdP + embedded outpost (proxy provider forward-auth). # Draft — do NOT apply as-is: # - secret values are placeholders; create them from Vaultwarden/ESO first # - requires the authentik user/DB on postgresql.haven (see README.md) # - requires DNS record for auth.haven -> ingress IP (user manages DNS) --- apiVersion: v1 kind: Secret metadata: name: authentik-secrets namespace: auth type: Opaque stringData: postgres_password: "CHANGE_ME" # Vaultwarden -> ESO later secret_key: "CHANGE_ME" # `openssl rand -base64 60` bootstrap_password: "CHANGE_ME" # initial akadmin password bootstrap_token: "CHANGE_ME" # outpost token --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: authentik-media namespace: auth spec: accessModes: [ReadWriteOnce] storageClassName: nfs-fast-client # verified: exists in cluster (nfs-client is also default) resources: requests: storage: 2Gi --- # Server (web + API) apiVersion: apps/v1 kind: Deployment metadata: name: authentik-server namespace: auth spec: replicas: 1 selector: matchLabels: { app: authentik, component: server } template: metadata: labels: { app: authentik, component: server } spec: containers: - name: server image: ghcr.io/goauthentik/server:2026.8 args: [server] env: - name: AUTHENTIK_SECRET_KEY valueFrom: { secretKeyRef: { name: authentik-secrets, key: secret_key } } - name: AUTHENTIK_POSTGRESQL__HOST value: postgresql.haven - name: AUTHENTIK_POSTGRESQL__NAME value: authentik - name: AUTHENTIK_POSTGRESQL__USER value: authentik - name: AUTHENTIK_POSTGRESQL__PASSWORD valueFrom: { secretKeyRef: { name: authentik-secrets, key: postgres_password }, } - name: AUTHENTIK_BOOTSTRAP_PASSWORD valueFrom: { secretKeyRef: { name: authentik-secrets, key: bootstrap_password }, } - name: AUTHENTIK_BOOTSTRAP_TOKEN valueFrom: { secretKeyRef: { name: authentik-secrets, key: bootstrap_token }, } - name: AUTHENTIK_ERROR_REPORTING__ENABLED value: "false" ports: - { containerPort: 9000, name: http } - { containerPort: 9443, name: https } readinessProbe: httpGet: { path: /-/health/ready/, port: 9000 } initialDelaySeconds: 20 periodSeconds: 10 livenessProbe: httpGet: { path: /-/health/live/, port: 9000 } initialDelaySeconds: 40 periodSeconds: 20 resources: requests: { cpu: 250m, memory: 512Mi } limits: { memory: 1Gi, cpu: 1000m } volumeMounts: - { name: media, mountPath: /media } volumes: - name: media persistentVolumeClaim: { claimName: authentik-media } --- # Worker (policies, outpost management, scheduled tasks) apiVersion: apps/v1 kind: Deployment metadata: name: authentik-worker namespace: auth spec: replicas: 1 selector: matchLabels: { app: authentik, component: worker } template: metadata: labels: { app: authentik, component: worker } spec: containers: - name: worker image: ghcr.io/goauthentik/server:2026.8 args: [worker] env: # same env as server; kept duplicated for a flat draft manifest - name: AUTHENTIK_SECRET_KEY valueFrom: { secretKeyRef: { name: authentik-secrets, key: secret_key } } - name: AUTHENTIK_POSTGRESQL__HOST value: postgresql.haven - name: AUTHENTIK_POSTGRESQL__NAME value: authentik - name: AUTHENTIK_POSTGRESQL__USER value: authentik - name: AUTHENTIK_POSTGRESQL__PASSWORD valueFrom: { secretKeyRef: { name: authentik-secrets, key: postgres_password }, } - name: AUTHENTIK_BOOTSTRAP_PASSWORD valueFrom: { secretKeyRef: { name: authentik-secrets, key: bootstrap_password }, } - name: AUTHENTIK_BOOTSTRAP_TOKEN valueFrom: { secretKeyRef: { name: authentik-secrets, key: bootstrap_token }, } - name: AUTHENTIK_ERROR_REPORTING__ENABLED value: "false" resources: requests: { cpu: 200m, memory: 512Mi } limits: { memory: 1Gi, cpu: 1000m } --- apiVersion: v1 kind: Service metadata: name: authentik namespace: auth spec: selector: { app: authentik, component: server } ports: - { name: http, port: 80, targetPort: 9000 } --- # Embedded outpost — runs the proxy providers; this is what ingress-nginx # calls for /auth/nginx on every use-sso-auth ingress. apiVersion: apps/v1 kind: Deployment metadata: name: authentik-outpost namespace: auth spec: replicas: 1 selector: matchLabels: { app: authentik, component: outpost } template: metadata: labels: { app: authentik, component: outpost } spec: containers: - name: outpost image: ghcr.io/goauthentik/proxy:2026.8 env: - name: AUTHENTIK_HOST value: http://authentik.auth.svc.cluster.local - name: AUTHENTIK_INSECURE value: "true" - name: AUTHENTIK_TOKEN valueFrom: { secretKeyRef: { name: authentik-secrets, key: bootstrap_token }, } ports: - { containerPort: 9000, name: http } readinessProbe: httpGet: { path: /outpost.goauthentik.io/ping, port: 9000 } initialDelaySeconds: 10 periodSeconds: 10 resources: requests: { cpu: 200m, memory: 512Mi } limits: { memory: 1Gi, cpu: 1000m } --- apiVersion: v1 kind: Service metadata: name: authentik-outpost namespace: auth spec: selector: { app: authentik, component: outpost } ports: - { name: http, port: 80, targetPort: 9000 } --- # SSO portal (user-facing login) — auth.haven apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: authentik namespace: auth spec: ingressClassName: traefik rules: - host: auth.haven http: paths: - path: / pathType: Prefix backend: { service: { name: authentik, port: { number: 80 } } } --- # Outpost route — the /outpost.goauthentik.io path must resolve on the same # host the protected apps redirect to. Kept as a separate ingress so it can # also be attached to other hosts later if needed (do NOT give it # use-sso-auth — that would create an auth loop). apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: authentik-outpost namespace: auth spec: ingressClassName: traefik rules: - host: auth.haven http: paths: - path: /outpost.goauthentik.io pathType: Prefix backend: { service: { name: authentik-outpost, port: { number: 80 } } }