removing auth ns

This commit is contained in:
2026-09-02 19:56:08 -03:00
parent fa8ca940f1
commit ff8bd2cb3e
4 changed files with 0 additions and 406 deletions
-99
View File
@@ -1,99 +0,0 @@
# Auth (Authentik + Kyverno SSO annotation policy)
Draft manifests only — nothing applied yet. Convention: any Ingress annotated
with `use-sso-auth: "true"` gets the Authentik forward-auth annotations injected
by the Kyverno ClusterPolicy (`auth/sso-auth-policy.yaml`).
## Deploy order
1. **Authentik** (`auth/authentik.yaml`) — IdP + embedded outpost. Needs a
Postgres user/DB on postgresql.haven first (see below), plus secrets from
Vaultwarden/ESO.
2. **Proxy provider** — create in Authentik UI (or via API) once it's up:
one provider per app you want header-auth'd, mode "forward_auth (single
app)", or a domain-level provider with the embedded outpost.
3. **Kyverno** (`auth/kyverno-helm.yaml`) — policy engine.
4. **SSO policy** (`auth/sso-auth-policy.yaml`) — expands `use-sso-auth: "true"`
into `auth-url` / `auth-signin` / `auth-response-headers` annotations.
5. Annotate ingresses: `kubectl annotate ingress <name> -n <ns> use-sso-auth=true`
and mirror the change in this repo.
## Postgres bootstrap (one-time, on postgresql.haven)
```sql
CREATE USER authentik WITH PASSWORD '<from-vaultwarden>';
CREATE DATABASE authentik OWNER authentik;
```
## Notes
- Outpost URL used everywhere is `https://auth.haven` — add DNS + ingress for
the outpost before annotating anything.
- Apps that should *consume* the injected `X-Authentik-*` headers (Grafana auth
proxy, Paperless remote-user, OpenWebUI trusted headers) need their own env
changes; those are app-side, not covered by the policy.
- API/WebSocket-heavy apps (arr stack, qBittorrent) should NOT get the
annotation on API paths — either skip the annotation or exclude paths.
## Which apps get the annotation (scoping)
Three tiers, applied per ingress — never blanket:
1. **OIDC tier** (no annotation, wire native OIDC in the app instead):
grafana, paperless, affine, openwebui, vaultwarden, beszel, slink.
Proper logout, group mapping, zero API breakage.
2. **Forward-auth tier** (`use-sso-auth: "true"`): browser-only utilities with
no real auth — it-tools, notepad, searxng, homepage, archivebox,
stirlingpdf, file-nginx, code-config, havenllo, own apps (chacal,
mindforge) if wanted.
3. **Hands off** (built-in auth is fine, forward-auth breaks clients):
sonarr, radarr, prowlarr, qbittorrent, adguard, changedetection,
uptimekuma, cloudreve (WebDAV), jellyfin (clients can't do redirects —
only the community SSO plugin route exists).
## Pre-annotation checklist (per new app)
Forward-auth breakage is loud and immediate if you look in the right places.
Before annotating any real hostname:
1. **Ask: what talks to this app that isn't a human in a browser?**
Mobile/desktop apps with own login, API-key consumers, push/webhook
receivers, cronjobs curling through the ingress, WebDAV/RSS → any of
those = hands off (tier 3) or exclude paths. "Just me in a browser" =
safe.
2. **Canary first:** create a scratch ingress for the same service
(`<app>-test.haven`) with the annotation; leave the original untouched
for ~a week. Forgotten integrations keep hitting the original and only
break the canary — instant rollback
(`kubectl annotate ingress <n> -n <ns> use-sso-auth-`).
3. **Grep the docs** (30s): "reverse proxy", "trusted header", "API key",
"webhook", "basic auth". A "running behind a reverse proxy" doc section
is where landmines are documented.
4. **Header-trust hygiene:** apps consuming `X-Authentik-*` must be
reachable ONLY through the ingress (no NodePort/exposed port, otherwise
LAN clients can forge headers straight to the pod). Keep built-in local
login enabled; never set SSO-only mode.
## Files
- `kyverno-helm.yaml` — Kyverno install values
- `sso-auth-policy.yaml` — ClusterPolicy: `use-sso-auth` → nginx auth annotations
- `authentik.yaml` — Authentik server/worker + outpost, Postgres PVC, ingress
## Status / when to actually deploy this (decision from 2026-08-28)
NOT deployed — deliberate. Sole user, low login frequency, everything
reachable via wg-easy, so SSO solves a problem that doesn't exist. The
`*.ivanch.me` public ingresses were reviewed instead: exposure without usage
is pure risk, and the right fix is removing exposure (VPN-only), not adding
an IdP.
Pull the trigger only if one of these becomes true:
1. A second person uses the homelab regularly (SSO value scales with users).
2. Something must be exposed that can't sit behind VPN (third-party
webhooks/callbacks) — then public tier gets `use-sso-auth` + 2FA.
3. Login friction on the OIDC apps (grafana/paperless/affine/openwebui/
vaultwarden/beszel/slink) actually annoys on a weekly basis.
Until then this folder is a shelf-ready draft; cost of keeping it is zero.
-244
View File
@@ -1,244 +0,0 @@
# 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 } } }
-24
View File
@@ -1,24 +0,0 @@
# Kyverno — policy engine. Install with:
# helm repo add kyverno https://kyverno.github.io/kyverno
# helm upgrade --install kyverno kyverno/kyverno -n kyverno --create-namespace -f auth/kyverno-helm.yaml
# The only consumer of Kyverno here is the use-sso-auth mutation policy;
# if you later drop it, Kyverno can be removed with no other impact.
admissionController:
replicas: 1
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
backgroundController:
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
cleanupController:
enabled: false
reportsController:
enabled: false
-39
View File
@@ -1,39 +0,0 @@
# ClusterPolicy: expands the single `use-sso-auth: "true"` Ingress annotation
# into the ingress-nginx forward-auth annotations pointed at the Authentik
# embedded outpost.
#
# Test before applying to real ingresses:
# kubectl apply -f auth/sso-auth-policy.yaml
# kubectl annotate ingress -n default homepage use-sso-auth=true --dry-run=server -o yaml # check annotations get injected
# # remove the test annotation afterwards
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: inject-sso-auth
spec:
validationFailureAction: Audit
background: false
rules:
- name: authentik-forward-auth
match:
any:
- resources:
kinds: [Ingress]
preconditions:
all:
- key: "{{ request.object.metadata.annotations.\"use-sso-auth\" || '' }}"
operator: Equals
value: "true"
mutate:
patchStrategicMerge:
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-url: https://auth.haven/outpost.goauthentik.io/auth/nginx
nginx.ingress.kubernetes.io/auth-signin: https://auth.haven/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
# NOTE: no auth-snippet used — ingress-nginx 1.15 rejects snippet
# annotations by default (allow-snippet-annotations=false, your
# controller ConfigMap is empty so it uses the default).
# ingress-nginx already forwards X-Original-URL to the auth
# backend automatically, which is all Authentik needs.
nginx.ingress.kubernetes.io/auth-response-headers: X-Authentik-Username,X-Authentik-Email,X-Authentik-Groups,X-Authentik-Name,X-Authentik-Metadata