Files
axion1337.chat-gitops/docs/deployment-guides/09-wiki-forward-auth.md
T
Thore Cimbal a661ceda11 docs: prepare Authentik forward-auth for the Docusaurus wiki (not deployed)
Docusaurus is static and has no auth of its own, so the gate goes in Traefik in
front of it via an Authentik proxy outpost. Guide 09 carries the complete,
ready-to-apply config: the Authentik blueprint (forward_single proxy provider +
application + wiki-zugang group + policy binding) and the Overmind side (proxy
outpost container + Traefik forwardAuth middleware). Deliberately kept as a guide,
not merged into the applied blueprint ConfigMap: nothing goes live until the
wiki hostname (#0024) is settled and the outpost token (a credential) is created
by sorb. Dedicated outpost on Overmind so per-request checks stay local and only
the login redirect crosses the VPN. Indexed in the guides README.
2026-08-11 12:00:00 +00:00

7.2 KiB

Docusaurus-Wiki hinter Authentik (Forward-Auth)

Status: vorbereitet, nicht ausgerollt · Entscheidung: bei Docusaurus bleiben, Zugang per Authentik einschränken (DOC-03/#0020, bei Docusaurus)

Docusaurus ist ein statischer Site-Generator — kein Nutzermodell, kein Login. Der Zugang wird deshalb im Reverse-Proxy davor erzwungen: Traefik fragt bei jedem Request einen Authentik-Outpost, ob eine gültige Sitzung vorliegt, und leitet sonst zu auth.axion1337.chat um. Erst nach Login gibt Traefik die statischen Seiten frei. Es ist ein Alles-oder-nichts-Tor (wer in der Gruppe wiki-zugang ist, sieht das ganze Wiki; sonst nichts) — für Bereichs-Rechte bräuchte es BookStack (ADR-0007), das war aber ausdrücklich nicht gewollt.

Topologie

Das Wiki läuft als Dokploy-Stack auf Overmind (git.lab/homelab/wiki, axionwiki.lab), Authentik im K3s-Cluster auf Hetzner. Deshalb ein eigener Proxy-Outpost als Container auf Overmind, statt des eingebetteten Outposts in Hetzner: So bleiben die Auth-Subrequests lokal auf Overmind — nur die Login-Umleitung quert den Site-to-Site-VPN zu auth.axion1337.chat. Das passt zur Leitlinie „das Lab hängt nicht am Prod-Host": ist eine Sitzung erst gesetzt, liest sich das Wiki im Lab auch ohne ständige Rückfrage nach Hetzner.

Browser ──▶ Traefik (Overmind) ──forwardAuth──▶ authentik-proxy (Overmind, :9000)
   │                                                    │ Sitzung? nein ──▶ 302
   └────────────── Login-Redirect ─────────────▶ auth.axion1337.chat (Hetzner, via VPN)

Teil 1 — Authentik-Blueprint (deklarativ)

Als neues Dokument in apps/authentik/authentik-blueprints.yaml einfügen (gleiche ConfigMap wie matrix-oidc-provider.yaml). Erst nach Klärung von #0024 einfügenexternal_host muss exakt dem echten Wiki-Host entsprechen.

  wiki-forward-auth.yaml: |
    # yaml-language-server: $schema=https://goauthentik.io/blueprints/schema.json
    version: 1
    metadata:
      name: wiki-forward-auth
      labels:
        blueprints.goauthentik.io/instantiate: "true"
    entries:
      # Proxy-Provider im Forward-Auth-Modus. Kein internal_host (das wäre der
      # Proxy-Modus) — forward_single reicht Traefik nur das Ja/Nein zurück.
      - model: authentik_providers_proxy.proxyprovider
        state: present
        identifiers:
          name: ThreadNet Wiki
        id: wiki_proxy_provider
        attrs:
          mode: forward_single
          # MUSS dem echten Wiki-Host entsprechen (#0024: axionwiki.lab vs wiki.lab).
          external_host: https://axionwiki.lab
          authorization_flow: !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
          invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
          access_token_validity: hours=24

      - model: authentik_core.application
        state: present
        identifiers:
          slug: wiki
        id: wiki_app
        attrs:
          name: ThreadNet Wiki
          provider: !KeyOf wiki_proxy_provider
          meta_description: Internes Docusaurus-Wiki, nur Gruppe wiki-zugang
          policy_engine_mode: any
          open_in_new_tab: true

      # Zugangsbeschränkung: nur Mitglieder dieser Gruppe passieren das Tor.
      - model: authentik_core.group
        state: present
        identifiers:
          name: wiki-zugang
        id: wiki_group

      - model: authentik_policies.policybinding
        state: present
        identifiers:
          target: !KeyOf wiki_app
          group: !KeyOf wiki_group
          order: 0
        attrs:
          enabled: true
          negate: false

⚠️ Vor dem Merge von Hand verifizieren, nicht auf Flux vertrauen — ein Blueprint-Fehler scheitert still (Lehre aus dem matrix-recovery-Fix):

kubectl exec -n authentik deploy/authentik-server -- \
  ak apply_blueprint /blueprints/... # bzw. den ConfigMap-Pfad; auf Fehlerausgabe achten

Teil 2 — Outpost + Token (Authentik-UI, sorb)

Der Outpost trägt ein Token — das ist ein Credential, kommt nicht ins Repo.

  1. Authentik → Applications → Outposts → Create: Typ Proxy, Name wiki-forward-auth, Provider ThreadNet Wiki zuweisen.
  2. Das erzeugte Outpost-Token kopieren (View-Token) — es geht gleich in den Overmind-Stack (Teil 3), nirgends sonst hin.
  3. Directory → Groups → wiki-zugang: die internen Nutzer aufnehmen, die das Wiki sehen dürfen.

Teil 3 — Overmind: Outpost-Container + Traefik (git.lab/homelab/wiki)

Neben den Docusaurus-Service in den Dokploy-/Compose-Stack. Image-Tag auf die laufende Authentik-Version pinnen (Outpost- und Server-Version müssen passen).

services:
  authentik-proxy:
    image: ghcr.io/goauthentik/proxy:2024.x   # == laufende Authentik-Version
    environment:
      AUTHENTIK_HOST: https://auth.axion1337.chat
      AUTHENTIK_INSECURE: "false"
      AUTHENTIK_TOKEN: ${WIKI_OUTPOST_TOKEN}   # aus Teil 2, als Dokploy-Secret
    labels:
      traefik.enable: "true"
      traefik.http.routers.wiki-authentik.rule: "Host(`axionwiki.lab`) && PathPrefix(`/outpost.goauthentik.io/`)"
      traefik.http.routers.wiki-authentik.service: wiki-authentik
      traefik.http.services.wiki-authentik.loadbalancer.server.port: "9000"

  # bestehender Docusaurus-Service — nur die Auth-Middleware ergänzen:
  wiki:
    labels:
      traefik.enable: "true"
      traefik.http.routers.wiki.rule: "Host(`axionwiki.lab`)"
      traefik.http.routers.wiki.middlewares: "wiki-auth@docker"
      traefik.http.middlewares.wiki-auth.forwardauth.address: "http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik"
      traefik.http.middlewares.wiki-auth.forwardauth.trustForwardHeader: "true"
      traefik.http.middlewares.wiki-auth.forwardauth.authResponseHeaders: "X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid"

Beide Services müssen im selben Traefik-Netz liegen. Der /outpost.goauthentik.io/- Router ohne die Auth-Middleware (sonst Redirect-Schleife).

Abhängigkeiten

  • #0024 (Wiki-Hostname) — blockierend: external_host, der Traefik-Host() und der Cookie-Scope müssen alle auf denselben Namen zeigen.
  • #0018 (Wiki-Rollout) — sollte abgeschlossen sein, bevor das Tor davor kommt.
  • Site-to-Site-VPN — die Login-Umleitung braucht auth.axion1337.chat vom Browser aus erreichbar; interne Nutzer im Lab/über VPN erreichen beides.

Verifikation

  1. Unauthentifiziert https://axionwiki.lab302 auf auth.axion1337.chat.
  2. Login als wiki-zugang-Mitglied → Wiki lädt.
  3. Login als Nicht-Mitglied → 403 (Policy greift).
  4. Gegenprobe: auth.axion1337.chat per Netzausfall kurz nicht erreichbar → bestehende Sitzung liest weiter (lokaler Outpost), nur neuer Login blockiert.

Was hier bewusst offen bleibt

  • Nichts ist live geschaltet — der Blueprint liegt als Vorlage hier, nicht in der angewandten ConfigMap; der Outpost-Token ist sorbs Schritt.
  • Kein Bereichs-Schutz — das ist die Grenze von Docusaurus + Forward-Auth; wenn je granulare Rechte nötig werden, ist das der Punkt, an dem ADR-0007 (BookStack) wieder aufgemacht gehört.