Install via Docker
docker run -d \
--name authelia \
--restart unless-stopped \
-p 127.0.0.1:9091:9091 \
-v ./config:/config \
authelia/authelia:latest
Configuration (single-file)
./config/configuration.yml:
theme: dark
default_2fa_method: totp
log: { level: info }
server:
address: 'tcp://0.0.0.0:9091/'
totp:
issuer: lab.example.com
algorithm: sha1
session:
secret: <random-32-chars>
expiration: 1h
inactivity: 10m
remember_me: 1M
cookies:
- domain: lab.example.com
authelia_url: https://auth.lab.example.com
default_redirection_url: https://lab.example.com
storage:
encryption_key: <random-32-chars>
local:
path: /config/db.sqlite3
# Authentication backend — users + groups
authentication_backend:
file:
path: /config/users_database.yml
password:
algorithm: argon2
argon2: { variant: argon2id, iterations: 3, memory: 65536, parallelism: 4 }
# Per-resource access rules
access_control:
default_policy: deny
rules:
- domain: "public.lab.example.com"
policy: bypass
- domain: "*.lab.example.com"
policy: one_factor # username/password OK
- domain: "admin.lab.example.com"
subject: "group:admin"
policy: two_factor # require TOTP/WebAuthn
- domain: "vault.lab.example.com"
subject: "group:admin"
policy: two_factor
methods: [GET, POST]
# Notifications (for 2FA setup emails)
notifier:
smtp:
username: authelia@example.com
password: <pw>
host: smtp.example.com
port: 587
sender: "Authelia <authelia@example.com>"
Users database (file backend)
# Generate Argon2id password hash
docker run --rm authelia/authelia:latest authelia crypto hash generate \
argon2 --password 'mySecretPassword'
# ./config/users_database.yml
users:
amir:
displayname: "Amir Eslampanah"
password: "$argon2id$v=19$m=65536,t=3,p=4$..."
email: amir@example.com
groups: [admin, users]
bob:
displayname: "Bob"
password: "$argon2id$v=19$..."
email: bob@example.com
groups: [users]
For LDAP / Active Directory backend, configure authentication_backend.ldap instead. Authelia validates against the directory at login.
Wire to Caddy (forward-auth)
# Caddyfile
auth.lab.example.com {
reverse_proxy 127.0.0.1:9091
}
# Protected app
grafana.lab.example.com {
forward_auth 127.0.0.1:9091 {
uri /api/verify?rd=https://auth.lab.example.com/
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy 127.0.0.1:3000
}
prometheus.lab.example.com {
forward_auth 127.0.0.1:9091 {
uri /api/verify?rd=https://auth.lab.example.com/
copy_headers Remote-User Remote-Groups
}
reverse_proxy 127.0.0.1:9090
}
The flow: user visits grafana.lab.example.com; Caddy calls Authelia; if not authenticated, Caddy redirects to auth.lab.example.com; user logs in; Authelia sets a session cookie scoped to *.lab.example.com; future requests to any subdomain skip the redirect.
Wire to nginx
# Auth portal
server {
server_name auth.lab.example.com;
listen 443 ssl;
location / { proxy_pass http://127.0.0.1:9091; }
}
# Protected app
server {
server_name grafana.lab.example.com;
listen 443 ssl;
location /authelia {
internal;
proxy_pass http://127.0.0.1:9091/api/verify;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
}
location / {
auth_request /authelia;
auth_request_set $target_url $scheme://$http_host$request_uri;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
error_page 401 =302 https://auth.lab.example.com/?rd=$target_url;
proxy_pass http://127.0.0.1:3000;
}
}
Wire to Traefik (the cleanest)
# traefik.yml middleware
http:
middlewares:
authelia:
forwardAuth:
address: "http://authelia:9091/api/verify?rd=https://auth.lab.example.com/"
trustForwardHeader: true
authResponseHeaders:
- "Remote-User"
- "Remote-Groups"
- "Remote-Name"
- "Remote-Email"
# Per-service: traefik.http.routers.grafana.middlewares=authelia@file
Trusted header forwarding to the app
Once authenticated, Authelia forwards the user's identity via Remote-User, Remote-Groups, Remote-Name, Remote-Email headers. Apps that understand "trusted-header" auth (Grafana, Gitea / Forgejo, Jellyfin, Plex) can consume these directly. For apps that don't, they still get auth without knowing about Authelia.
OIDC support (the bridge mode)
Authelia 4.30+ can also act as a (limited) OIDC provider. For apps that need OIDC but can't do trusted-header, add:
identity_providers:
oidc:
hmac_secret: <random>
issuer_private_key: <contents of key.pem>
clients:
- id: grafana
secret: '$pbkdf2-sha512$...' # generate via authelia crypto hash
public: false
authorization_policy: two_factor
redirect_uris:
- https://grafana.lab.example.com/login/generic_oauth
scopes: [openid, groups, email, profile]
grant_types: [authorization_code]
response_types: [code]
response_modes: [form_post]
Now Grafana can be configured with OIDC pointing at Authelia. Mix-and-match: forward-auth for some apps + OIDC for others.
2FA setup flow
First login → Authelia prompts to register TOTP. User scans the QR code with Authy / 1Password / Google Authenticator; sets a name. Subsequent logins ask for password + TOTP. WebAuthn / FIDO2 works the same way under "Methods" in the user portal — tap a security key once to enroll.
For per-resource policy two_factor, login forces 2FA before access. For one_factor, password is enough.
Authelia vs alternatives
- Authentik (see that tutorial) — full IdP with own UI / flows / user store. Use when you want SAML / SCIM / complex policy.
- Keycloak — the heavyweight; massive feature surface; Java-heavy.
- Dex (see that tutorial) — OIDC-only; federates upstream; no UI / sessions for forward-auth.
- oauth2-proxy — the older forward-auth tool; great if you already use an upstream IdP and just need to enforce auth at the reverse proxy.
- Caddy security plugin — for Caddy-only setups; tighter integration but Caddy-locked.
When Authelia is the right pick
- "I have 5-30 self-hosted apps + want to put SSO + 2FA in front of them with minimum operational drama."
- Forward-auth is the architecture (reverse proxy already in place).
- You don't need full IdP features (SAML, SCIM, complex auth flows).
When it isn't
- Need to be an IdP for other systems — Authentik / Keycloak.
- Need centralized user management across many orgs / tenants — full IdP.
- SAML SP / IdP — Authentik / Keycloak.