docs: document outpost router + priority gotcha for forward-auth

The Traefik example was missing the veola-outpost router (PathPrefix
/outpost.goauthentik.io/ -> authentik service) and the header-strip
middleware, so a fresh deploy following it would 404 on Sign out.

Add both, plus a prominent note: the outpost router must outrank the
catch-all Host(...) router. Traefik's default priority is rule length,
so Authentik's docs value of priority:15 silently loses once the
hostname rule exceeds 15 chars (e.g. veola.parodia.dev = 25), letting
the catch-all swallow /outpost.goauthentik.io/sign_out into Veola's
404. Use a high explicit priority (100).
This commit is contained in:
prosolis
2026-06-20 16:03:06 -07:00
parent 56fe8d7c88
commit 95272ca4c5

View File

@@ -47,19 +47,58 @@ http:
- X-authentik-email
- X-authentik-name
- X-authentik-groups
# Strip client-supplied identity headers on ingress so only the outpost
# can set them (runs before `authentik` on the protected router).
authentik-strip:
headers:
customRequestHeaders:
X-authentik-username: ""
X-authentik-email: ""
X-authentik-name: ""
X-authentik-groups: ""
X-authentik-uid: ""
routers:
veola:
rule: "Host(`veola.example.com`)"
service: veola
middlewares:
- authentik-strip
- authentik
tls:
certResolver: letsencrypt
# The outpost's own endpoints (callback, start, sign_out) must go straight
# to Authentik, NOT through the forwardAuth-protected `veola` router. This
# router has NO auth middleware and points at the authentik service.
veola-outpost:
rule: "Host(`veola.example.com`) && PathPrefix(`/outpost.goauthentik.io/`)"
priority: 100
service: authentik
tls:
certResolver: letsencrypt
services:
authentik:
loadBalancer:
servers:
- url: "http://authentik-server:9000/"
```
Traefik must strip any client-supplied `X-Authentik-*` and `X-Forwarded-*`
headers on ingress so only the outpost can set them.
**Router priority — important.** Both routers match the Veola host, so the more
specific `veola-outpost` must win. Traefik's *default* priority is the rule
length, so the catch-all `veola` router (`Host(...)`) gets a priority equal to
its length (e.g. `Host(`veola.parodia.dev`)` = 25). Authentik's docs example
sets the outpost router to `priority: 15`, which **silently loses** whenever the
hostname rule is longer than 15 chars — the catch-all then swallows
`/outpost.goauthentik.io/*` and hands it to Veola, which 404s. Symptom: clicking
**Sign out** lands on `/outpost.goauthentik.io/sign_out` with a plain
`404 page not found`. Fix: give `veola-outpost` a high explicit priority (e.g.
`100`) so it always beats the catch-all.
(Login still works even when the outpost router loses, because the outpost
intercepts `callback`/`start` during the forwardAuth `/auth/traefik` round-trip;
`sign_out` is the one path that genuinely needs the dedicated router.)
## Break-glass