Learn Authelia - Traefik Integration
Episode 14 of 31

Learn Authelia - Traefik Integration

This episode integrates Authelia with Traefik through the ForwardAuth middleware: defining the middleware in dynamic config, installing it via Docker labels, copying the Remote-User identity headers, up to a complete compose example that protects a service.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 13 you built an authentication gateway in NGINX with auth_request. In episode 14 we apply the same pattern — proxy asks, Authelia answers — to the proxy most familiar with the container world: Traefik. Where NGINX requires manual config blocks, Traefik offers something different: a forwardAuth middleware attached per router, often configured entirely through Docker labels without touching a config file.

Traefik is a reverse proxy born in the container era: it reads service declarations from providers like Docker and determines routing based on labels attached to containers. That means securing an application with Authelia can be as simple as adding one middlewares label to that service.

An analogy: NGINX is a security officer managed through a thick manual; Traefik is a security officer who obeys command boards posted at each door. Both guard the same building — the difference is how we give instructions.

The ForwardAuth Middleware Concept

Middleware is Traefik's request-processing pipeline. forwardAuth works by sending a request to a specified address; the response determines the fate of the original request:

  • A 2xx status from Authelia means allow and forward the request.
  • Any other status is handled according to Authelia's response — usually a redirect to the portal.

The core configuration in dynamic config (YAML file):

dynamic/authelia.yml — ForwardAuth middleware
http:
  middlewares:
    authelia:
      forwardAuth:
        address: "http://authelia:9091/api/authz/forward-auth"
        trustForwardHeader: true
        maxResponseBodySize: 8192
        authResponseHeaders:
          - Remote-User
          - Remote-Groups
          - Remote-Email
          - Remote-Name

The key options:

  • address — the Authelia endpoint. Note the path /api/authz/forward-auth, not the portal.
  • trustForwardHeader — tells Authelia to trust the X-Forwarded-* headers Traefik sends. Authelia uses these headers to determine the scheme, host, and real IP for evaluating access control rules.
  • authResponseHeaders — the Authelia response headers copied into the request forwarded to the application. This is the Trusted Header SSO mechanism: the application receives the user identity via Remote-User and friends.

Installing the Middleware via Docker Labels

Traefik's advantage in Docker is that everything can be declarative through labels. The same middleware definition above can be written as labels:

Service with middleware label
services:
  nextcloud:
    image: linuxserver/nextcloud
    labels:
      traefik.enable: "true"
      traefik.http.routers.nextcloud.rule: "Host(`nextcloud.example.com`)"
      traefik.http.routers.nextcloud.entryPoints: "websecure"
      traefik.http.routers.nextcloud.tls: "true"
      traefik.http.routers.nextcloud.middlewares: "authelia@file"

Note traefik.http.routers.nextcloud.middlewares: "authelia@file" — this is the magic line that attaches the authelia middleware to the nextcloud router. The @file suffix indicates the middleware is defined in a file provider (dynamic config), not via labels.

If you want to define the middleware via labels too (usually on the Authelia container), the pattern is the same:

Middleware labels on the Authelia container
labels:
  traefik.enable: "true"
  traefik.http.routers.authelia.rule: "Host(`auth.example.com`)"
  traefik.http.routers.authelia.entryPoints: "websecure"
  traefik.http.routers.authelia.tls: "true"
  traefik.http.middlewares.authelia.forwardauth.address: "http://authelia:9091/api/authz/forward-auth"
  traefik.http.middlewares.authelia.forwardauth.trustForwardHeader: "true"
  traefik.http.middlewares.authelia.forwardauth.maxResponseBodySize: "8192"
  traefik.http.middlewares.authelia.forwardauth.authResponseHeaders: "Remote-User,Remote-Groups,Remote-Email,Remote-Name"

Here the labels prefixed with traefik.http.middlewares.* define the middleware, and the Authelia router itself passes through that middleware so the portal stays accessible. Other services just write middlewares: "authelia@docker" to point to a middleware from these labels.

A Complete Compose Example

Let's assemble everything: Traefik, Authelia, and one protected application.

compose.yaml — Traefik + Authelia + app
networks:
  net: {}
 
services:
  traefik:
    image: traefik:v3
    restart: unless-stopped
    networks: [net]
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./dynamic:/etc/traefik/dynamic
    command:
      - --providers.docker=true
      - --providers.docker.exposedByDefault=false
      - --providers.file.directory=/etc/traefik/dynamic
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
 
  authelia:
    image: authelia/authelia
    restart: unless-stopped
    networks: [net]
    volumes:
      - ./config:/config
    labels:
      traefik.enable: "true"
      traefik.http.routers.authelia.rule: "Host(`auth.example.com`)"
      traefik.http.routers.authelia.entryPoints: "websecure"
      traefik.http.routers.authelia.tls: "true"
      traefik.http.routers.authelia.middlewares: "authelia@file"
 
  nextcloud:
    image: linuxserver/nextcloud
    restart: unless-stopped
    networks: [net]
    volumes:
      - ./nextcloud:/config
      - ./nextcloud/data:/data
    labels:
      traefik.enable: "true"
      traefik.http.routers.nextcloud.rule: "Host(`nextcloud.example.com`)"
      traefik.http.routers.nextcloud.entryPoints: "websecure"
      traefik.http.routers.nextcloud.tls: "true"
      traefik.http.routers.nextcloud.middlewares: "authelia@file"

An important note: --providers.docker.exposedByDefault=false ensures only containers with traefik.enable: "true" are published — a practice that prevents services from being accidentally exposed to the public.

Traefik v2 vs v3

Both versions use the same concept. The practical differences you should know:

  • Response header names — in v3, Traefik normalizes header names to lowercase when sending them. HTTP fundamentally treats header names case-insensitively, but if an application demands a specific casing, adjust the authResponseHeaders list to match what the application reads.
  • Endpoint path — use /api/authz/forward-auth on v3 (the modern ForwardAuth endpoint); the old /api/verify endpoint still works for compatibility, but isn't recommended for new installations.
  • maxResponseBodySize — an option limiting the auth response body size, useful for preventing unexpected responses from filling memory.

Warning

Make sure Traefik and Authelia are on the same Docker network (in the example: net). If they're separate, use the correct hostname in address — a wrong name means the middleware can never respond, and all requests to protected services will fail.

Testing the Integration

Once the stack is running:

  1. Access nextcloud.example.com without logging in — you should be redirected to the auth.example.com portal.
  2. Log in and complete MFA — redirected back to Nextcloud.
  3. Check Traefik logs with docker compose logs traefik to confirm the authelia@file middleware responds without errors.
  4. If Nextcloud supports auth headers, check that the Remote-User header arrives — the application will recognize the user without a login form.

Closing

This episode integrated Authelia with Traefik: understanding the forwardAuth middleware as a replacement for auth_request, defining middleware in dynamic config or Docker labels, choosing the address, trustForwardHeader, and authResponseHeaders options correctly, and assembling a complete compose setup that protects a service with a single label.

Traefik shows the power of the forward authentication pattern when combined with container-based declarations — one middleware definition, reused by all services. In episode 15 we look at the other end of the configuration spectrum: Caddy, the proxy known for its simple Caddyfile and automatic HTTPS. See you there!

Learn Authelia - Traefik Integration | Learn Authelia