From ba413f7b34f738a9bc8e99bcbbdba0609fee5c4b Mon Sep 17 00:00:00 2001 From: Konstantin Renner Date: Sat, 9 May 2026 20:01:18 +0200 Subject: [PATCH] paperless: gate every hostname behind authentik forward-auth Add nginx auth_request annotations to the paperless ingress and a matching forward_domain ProxyProvider + Application in the Authentik blueprint, attached to the embedded outpost. cookie_domain=renner.uno shares the session across all four paperless aliases (paperless.* and docs.*, both .renner.uno and .k.renner.uno). Also drop the half-built `Caddy docs.renner.uno` provider that was producing a phantom ak-outpost-caddy ingress conflicting with the paperless ingress on docs.renner.uno. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../apps/authentik/blueprints-configmap.yaml | 53 +++++++++++++++++++ kubernetes/apps/paperless/paperless.yaml | 11 ++++ 2 files changed, 64 insertions(+) diff --git a/kubernetes/apps/authentik/blueprints-configmap.yaml b/kubernetes/apps/authentik/blueprints-configmap.yaml index 519c0d63..06f693ee 100644 --- a/kubernetes/apps/authentik/blueprints-configmap.yaml +++ b/kubernetes/apps/authentik/blueprints-configmap.yaml @@ -25,12 +25,54 @@ data: attrs: local: true + # forward_domain provider for paperless. external_host points at + # the embedded outpost's public URL (where unauthenticated users + # are redirected to sign in). cookie_domain=renner.uno makes the + # session cookie shared across every *.renner.uno and + # *.k.renner.uno host, so all four paperless aliases use the same + # login. Ingress-side annotations on the paperless Ingress wire + # nginx auth_request to this outpost. + - id: paperless-provider + model: authentik_providers_proxy.proxyprovider + identifiers: + name: paperless + state: present + attrs: + authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]] + invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]] + mode: forward_domain + external_host: https://auth.renner.uno + cookie_domain: renner.uno + access_token_validity: hours=24 + refresh_token_validity: days=30 + intercept_header_auth: true + + - model: authentik_core.application + identifiers: + slug: paperless + state: present + attrs: + name: Paperless + slug: paperless + provider: !KeyOf paperless-provider + meta_launch_url: https://paperless.renner.uno + meta_description: "Paperless-ngx document management" + - model: authentik_outposts.outpost identifiers: name: authentik Embedded Outpost state: present attrs: service_connection: !KeyOf k8s-conn + # Forward-auth providers attached here are served by the + # embedded outpost on auth.renner.uno (and via the in-cluster + # authentik-server Service for nginx auth_request). Setting + # `providers` is authoritative — anything attached to the + # embedded outpost via the UI that is not listed here will be + # detached on reconcile. Add new gated apps to this list, not + # the UI. + providers: + - !KeyOf paperless-provider # `Caddy` and `Local Radius` carried `kubernetes_namespace: default` # in their config from the Proxmox-era data, which the chart Role @@ -124,3 +166,14 @@ data: identifiers: name: Local Docker connection state: absent + + # The previous UI-managed proxy provider for docs.renner.uno was + # half-built (forward_single mode with no internal_host) and only + # ever produced a phantom ingress that conflicted with paperless's + # claim on the same hostname. Drop it so Authentik tears down the + # auto-generated ak-outpost-caddy ingress; paperless now owns the + # docs.* aliases and is gated by the paperless provider above. + - model: authentik_providers_proxy.proxyprovider + identifiers: + name: Caddy docs.renner.uno + state: absent diff --git a/kubernetes/apps/paperless/paperless.yaml b/kubernetes/apps/paperless/paperless.yaml index a42eef16..b2afca51 100644 --- a/kubernetes/apps/paperless/paperless.yaml +++ b/kubernetes/apps/paperless/paperless.yaml @@ -144,6 +144,17 @@ metadata: annotations: cert-manager.io/cluster-issuer: letsencrypt-cluster nginx.ingress.kubernetes.io/proxy-body-size: "100m" + # Forward-auth into Authentik. Every request is bounced to the + # embedded outpost (in-cluster, no TLS) for an auth check; + # unauthenticated browsers are redirected to auth.renner.uno to + # sign in. Cookies are scoped to renner.uno via the matching + # forward_domain proxy provider in the Authentik blueprint, so + # all four paperless hostnames share the same session. + nginx.ingress.kubernetes.io/auth-url: "http://authentik-server.authentik.svc.cluster.local/outpost.goauthentik.io/auth/nginx" + nginx.ingress.kubernetes.io/auth-signin: "https://auth.renner.uno/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri" + nginx.ingress.kubernetes.io/auth-response-headers: "Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid" + nginx.ingress.kubernetes.io/auth-snippet: | + proxy_set_header X-Forwarded-Host $http_host; spec: ingressClassName: nginx rules: