Integrating Authentik with Traefik via the forwardAuth middleware: defining the middleware in dynamic config or Docker labels, pointing applications at the outpost endpoint, forwarding identity headers, and testing the integration with curl.

In episode 11, we understood the proxy provider foundation: the forward authentication concept, the outpost as the component running the provider, and the authorization flow from incoming request to identity header injection into the application. This episode applies that foundation to the proxy most at home in the container world: Traefik.
Authentik uses a pattern we already know: before a request is forwarded to an application, the reverse proxy asks the outpost. Traefik provides this facility through the forwardAuth middleware — a processing pipeline that sends the request to the outpost address and judges the fate of the original request from its response.
Analogy: you have a security guard (Traefik) receiving guests at the front of the building. Before opening the door, the guard calls the security center (Authentik outpost). Only if the security center answers "this person is known" is the door opened and the guest's identity announced over the loudspeaker — that's the X-authentik-* header.
The forwardAuth middleware in Traefik works simply:
The core configuration is defined in Traefik's dynamic config:
http:
middlewares:
authentik:
forwardAuth:
address: "http://outpost.example.com:9000/outpost.goauthentik.io/auth/traefik"
trustForwardHeader: true
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
- X-authentik-email
- X-authentik-name
- X-authentik-uid
- X-authentik-jwtOptions worth understanding:
address — the outpost endpoint for Traefik forward auth mode. Note the path /outpost.goauthentik.io/auth/traefik, not the Authentik portal. Port 9000 is the proxy outpost's HTTP port.trustForwardHeader — tells the outpost to trust the X-Forwarded-* headers sent by Traefik. These are the headers Authentik uses to know the scheme, host, and real IP of the request.authResponseHeaders — the list of headers from the outpost response copied into the request forwarded to the application. This is the Trusted Header SSO mechanism: the application recognizes the user from these headers without a login form.The headers applications use most are X-authentik-username, X-authentik-email, X-authentik-name, X-authentik-groups, and X-authentik-uid. Recent Authentik versions also provide X-authentik-jwt for JWT tokens, as well as X-authentik-meta-* headers carrying outpost and provider metadata.
Traefik's strength in the Docker ecosystem: routing configuration can be declared directly through container labels. The same middleware can be attached to a service with just one line:
services:
whoami:
image: traefik/whoami
labels:
traefik.enable: "true"
traefik.http.routers.whoami.rule: "Host(`whoami.example.com`)"
traefik.http.routers.whoami.entryPoints: "websecure"
traefik.http.routers.whoami.tls: "true"
traefik.http.routers.whoami.middlewares: "authentik@file"The magic sentence is in the last line: traefik.http.routers.whoami.middlewares: "authentik@file". The @file suffix indicates the authentik middleware is defined in a file provider, not via labels. If you want to define the middleware via labels, the prefix becomes traefik.http.middlewares.authentik.forwardauth.* and the suffix @docker.
There's one important requirement: all requests under the /outpost.goauthentik.io path must remain accessible without authentication. This path is used by the outpost to receive the OAuth2 response after the user logs in at the portal. Add a dedicated router with the rule Host(whoami.example.com) and PathPrefix(/outpost.goauthentik.io) forwarded straight to the outpost.
The proxy provider is run by an outpost. There are two common deployment choices:
http://authentik-server:9000/... (the compose service name).ghcr.io/goauthentik/proxy:latest image, configured through two environment variables:docker run -d \
--name authentik-proxy \
-p 9000:9000 \
-e AUTHENTIK_HOST=http://auth.example.com \
-e AUTHENTIK_TOKEN=token-rahasia-outpost \
ghcr.io/goauthentik/proxy:latestAUTHENTIK_HOST is Authentik's external URL, and AUTHENTIK_TOKEN is the outpost token created in the UI (Outpost → token). The Traefik middleware then points to http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik.
Tip
For starters, use an embedded outpost — one less service to manage. Move to a standalone proxy outpost when you need scale (many outpost containers) or want to offload load from the Authentik server.
Traefik v3 normalizes the copied header names to lowercase when forwarding to applications. HTTP treats header names case-insensitively, so applications that read headers case-insensitively have no problem. If an application demands specific casing, use authResponseHeadersRegex: "^X-authentik-" to copy all X-authentik- prefixed headers at once.
The middleware only handles whether the user is logged in. Authorization — whether the user may open this application — is evaluated by Authentik through policy bindings on the application (recall episode 6). This means you can protect ten applications with the same middleware but give each application different policies: the admin application requires the ops group, the dashboard application just requires anyone logged in.
For paths that may be accessed without authentication (for example /healthz or callback endpoints), set the Unauthenticated Paths on the proxy provider.
Logout is done via /outpost.goauthentik.io/sign_out on the protected application's host — the outpost deletes the Authentik session, then redirects back to the application.
Before testing the full login flow, make sure the outpost is publicly reachable under the application domain:
curl -v https://whoami.example.com/outpost.goauthentik.io/pingAn HTTP/2 204 (No Content) response means the outpost path is open and ready to use. If a 404 or 502 appears, check the dedicated router rule for /outpost.goauthentik.io — this is the number one cause of Traefik integration failures.
This episode integrated Authentik with Traefik: understanding the forwardAuth middleware and the /outpost.goauthentik.io/auth/traefik endpoint, defining the middleware in dynamic config or Docker labels, choosing the address, trustForwardHeader, and authResponseHeaders options correctly, choosing an embedded or standalone outpost, and testing the outpost path with curl.
Traefik shows how easy the forward authentication pattern is in the container world — one middleware, reused by all services. In episode 13, we review two other equally popular proxies: NGINX with auth_request and Caddy with forward_auth, then compare all three. See you there!