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: '5minutes'
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: 'AuthUser'
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.
For further actions, you may consider blocking this person and/or reporting abuse
