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).
109 lines
4.1 KiB
Markdown
109 lines
4.1 KiB
Markdown
# Authentik forward-auth (via Traefik)
|
|
|
|
Veola can delegate identity to Authentik using Traefik's `forwardAuth`
|
|
middleware. Veola itself does not speak OIDC; it trusts identity headers that
|
|
Authentik's proxy outpost sets, and matches/creates a local user by **email**.
|
|
Local password login stays available as a break-glass fallback.
|
|
|
|
## 1. Veola config
|
|
|
|
```toml
|
|
[auth]
|
|
mode = "forward"
|
|
trusted_proxies = ["172.18.0.0/16"] # CIDR(s) of the Traefik container/host
|
|
admin_group = "veola-admins" # Authentik group that grants admin
|
|
```
|
|
|
|
`trusted_proxies` is mandatory in forward mode: forward-auth headers are only
|
|
honored when the **direct** connection (before `X-Forwarded-For` rewriting)
|
|
comes from one of these CIDRs. Without it the headers are spoofable. Use the
|
|
address Traefik connects from (its Docker network range, or `127.0.0.1/32` if
|
|
co-located).
|
|
|
|
Header names default to Authentik's (`X-Authentik-Username`,
|
|
`X-Authentik-Email`, `X-Authentik-Name`, `X-Authentik-Groups`); override under
|
|
`[auth]` only if your outpost differs.
|
|
|
|
## 2. Authentik
|
|
|
|
- Create a **Proxy Provider** in *forward auth (single application)* mode with
|
|
the external host (e.g. `https://veola.example.com`).
|
|
- Bind it to an Application, and bind the embedded/standalone outpost.
|
|
- Create a group (default name `veola-admins`) and add operators who should be
|
|
Veola admins. Everyone else lands as a regular user. Role is re-synced from
|
|
the group on every request.
|
|
|
|
## 3. Traefik
|
|
|
|
```yaml
|
|
http:
|
|
middlewares:
|
|
authentik:
|
|
forwardAuth:
|
|
address: "http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
|
|
trustForwardHeader: true
|
|
authResponseHeaders:
|
|
- X-authentik-username
|
|
- 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/"
|
|
```
|
|
|
|
**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
|
|
|
|
`/login` and `/setup` still work for local password accounts. If Authentik is
|
|
down, reach Veola directly (bypassing the proxy) from a trusted network and log
|
|
in with a local admin account. Forward-auth is a no-op for connections that do
|
|
not originate from `trusted_proxies`.
|