Files
veola/deploy/authentik-forward-auth.md
prosolis 95272ca4c5 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).
2026-06-20 16:03:06 -07:00

4.1 KiB

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

[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

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.