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.
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
# 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ügen** — `external_host` muss exakt dem echten Wiki-Host entsprechen.
|
||||
|
||||
```yaml
|
||||
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):
|
||||
|
||||
```bash
|
||||
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).
|
||||
|
||||
```yaml
|
||||
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.lab` → **302** 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.
|
||||
@@ -16,6 +16,7 @@ Die Implementierungen wurden in dieser Reihenfolge durchgeführt. Für neue Setu
|
||||
| 6 | Moderationsbot (Draupnir) & Content Scanning | `06-moderation-content-scanning.md` | ✅ Deployed | Matrix Synapse |
|
||||
| 7 | Host-Wartungsbenachrichtigungen (unattended-upgrades) | `07-host-maintenance-notifications.md` | ✅ Deployed | Host-Ebene (kein K8s) |
|
||||
| 8 | @concierge — Gäste-Einladungen mit Ablauf | `08-concierge-gaeste-einladungen.md` | ⏳ Wartet auf Zugangsdaten | Matrix Synapse |
|
||||
| 9 | Docusaurus-Wiki hinter Authentik (Forward-Auth) | `09-wiki-forward-auth.md` | 📝 Vorbereitet, nicht ausgerollt | Authentik + Traefik (Overmind) |
|
||||
|
||||
---
|
||||
|
||||
@@ -102,6 +103,12 @@ per Mail + Matrix-Thread-Reply anstehende `unattended-upgrades`, bevor sie laufe
|
||||
Freischaltung nur durch Admin-Kommando im Matrix-Raum (Issue #48). Deployt, wartet auf
|
||||
Zugangsdaten (Matrix-Konto, Authentik-Token, Secret).
|
||||
|
||||
### [09-wiki-forward-auth.md](09-wiki-forward-auth.md)
|
||||
Statisches Docusaurus-Wiki hinter Authentik: Proxy-Provider (Forward-Auth) + Anwendung +
|
||||
Gruppe `wiki-zugang` als Blueprint, Proxy-Outpost-Container plus Traefik-Middleware auf
|
||||
Overmind. Vorbereitet, nicht ausgerollt — Blueprint als Vorlage im Guide, Outpost-Token
|
||||
und `wiki-zugang`-Mitglieder sind sorbs Schritt; blockiert auf Wiki-Hostname (#0024, DOC-03).
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Wartung & Troubleshooting
|
||||
|
||||
Reference in New Issue
Block a user