Authelia is an open-source authentication and authorization gateway that adds SSO, two-factor authentication, and policy-based access control in front of web applications, integrating natively with reverse proxies through forward-auth. This guide deploys Authelia using Docker Compose with Traefik handling automatic HTTPS, file-backed users, TOTP 2FA, and a sample whoami app protected by forward-auth. By the end, you'll have Authelia gating multiple subdomains with SSO and 2FA over HTTPS.
Set Up the Directory Structure
1. Create the project directory structure:
$ mkdir -p ~/authelia/{config,secrets,logs}
$ cd ~/authelia
2. Create the environment file:
$ nano .env
DOMAIN=example.com
LETSENCRYPT_EMAIL=admin@example.com
DNS A records for auth.${DOMAIN}, app.${DOMAIN}, and traefik.${DOMAIN} must point at the server.
Generate Authelia Secrets
1. Own the secrets directory:
$ sudo chown 8000:8000 ./secrets
$ sudo chmod 0700 ./secrets
2. Generate session, storage, and JWT secrets in one shot:
$ docker run --rm -u 8000:8000 -v ./secrets:/secrets docker.io/authelia/authelia:4.39 \
sh -c "cd /secrets && authelia crypto rand --length 64 session_secret.txt storage_encryption_key.txt jwt_secret.txt"
Write the Authelia Configuration
1. Create the configuration file:
$ nano config/configuration.yml
server:
address: 'tcp4://:9091'
log:
level: 'info'
file_path: '/var/log/authelia/authelia.log'
keep_stdout: true
identity_validation:
elevated_session:
require_second_factor: true
reset_password:
jwt_lifespan: '5 minutes'
jwt_secret: {{ secret "/secrets/jwt_secret.txt" | mindent 0 "|" | msquote }}
totp:
disable: false
issuer: 'example.com'
period: 30
skew: 1
authentication_backend:
file:
path: '/config/users.yml'
password:
algorithm: 'argon2'
argon2:
variant: 'argon2id'
iterations: 3
memory: 65535
parallelism: 4
key_length: 32
salt_length: 16
access_control:
default_policy: 'deny'
rules:
- domain: 'app.example.com'
policy: 'two_factor'
- domain: 'traefik.example.com'
policy: 'one_factor'
session:
name: 'authelia_session'
secret: {{ secret "/secrets/session_secret.txt" | mindent 0 "|" | msquote }}
cookies:
- domain: 'example.com'
authelia_url: 'https://auth.example.com'
regulation:
max_retries: 4
find_time: 120
ban_time: 300
storage:
encryption_key: {{ secret "/secrets/storage_encryption_key.txt" | mindent 0 "|" | msquote }}
local:
path: '/config/db.sqlite3'
notifier:
disable_startup_check: false
filesystem:
filename: '/config/notification.txt'
2. Generate an argon2 hash for the first user's password:
$ docker run --rm authelia/authelia:4.39 authelia crypto hash generate argon2 --password 'your-secure-password'
3. Create the user database with that hash:
$ nano config/users.yml
users:
authuser:
displayname: 'Auth User'
password: '$argon2id$v=19$m=65536,t=3,p=4$BpLnfgDsc2WD8F2q$Zis.ixdg9s/UOJYrs56b5QEZFiZECu0qZVNsIYxBaNJ7ucIL.nlxVCT5tqh8KHG8X4tlwCFm5r6NTOZZ5qRFN/'
email: 'authuser@example.com'
groups:
- 'admin'
Deploy with Docker Compose
1. Create the Docker Compose manifest:
$ nano docker-compose.yaml
services:
traefik:
image: traefik:v3.6
container_name: traefik
depends_on:
- authelia
command:
- "--api.dashboard=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- "./letsencrypt:/letsencrypt"
- "/var/run/docker.sock:/var/run/docker.sock:ro"
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.${DOMAIN}`)"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.middlewares=authelia@docker"
restart: unless-stopped
authelia:
image: authelia/authelia:4.39
container_name: authelia
volumes:
- "./secrets:/secrets:ro"
- "./config:/config"
- "./logs:/var/log/authelia"
environment:
TZ: "UTC"
X_AUTHELIA_CONFIG_FILTERS: "template"
labels:
- "traefik.enable=true"
- "traefik.http.routers.authelia.rule=Host(`auth.${DOMAIN}`)"
- "traefik.http.routers.authelia.entrypoints=websecure"
- "traefik.http.routers.authelia.tls.certresolver=letsencrypt"
- "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.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
restart: unless-stopped
whoami:
image: traefik/whoami
container_name: whoami
depends_on:
- authelia
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`app.${DOMAIN}`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
- "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
- "traefik.http.routers.whoami.middlewares=authelia@docker"
restart: unless-stopped
2. Start the services:
$ docker compose up -d
3. Verify the services are running:
$ docker compose ps
$ docker compose logs
Register TOTP and Test SSO
1. Open the login portal:
Navigate to https://auth.example.com and sign in as authuser.
2. Register a TOTP device:
Click Register device and capture the verification code from the filesystem notifier:
$ docker compose exec authelia cat /config/notification.txt
Scan the QR code with an authenticator app and enter the 6-digit code.
3. Visit a protected app:
Open https://app.example.com — the request redirects through Authelia for password + TOTP, then the whoami container returns the injected identity headers.
4. Confirm SSO:
Open https://traefik.example.com from the same browser — no re-authentication required.
Next Steps
Authelia is gating multiple subdomains with SSO and 2FA. From here you can:
- Protect more apps by adding
traefik.http.routers.<svc>.middlewares=authelia@dockerand a matchingaccess_controlrule - Switch the authentication backend to LDAP or OpenID Connect 1.0
- Configure SMTP under
notifierto deliver verification codes by email
For the full guide with additional tips, visit the original article on Vultr Docs.


























