Many self-hosted apps (dashboards, admin panels, download managers, monitoring UIs) have weak login pages, or none at all. Authelia sits in front of them as an authentication portal. Your reverse proxy asks Authelia whether each request is allowed, users log in once with two-factor authentication, and that session covers all your apps (single sign-on). It can also act as an OpenID Connect provider for apps that support OIDC.
How forward auth works
Browser ──▶ Nginx / Traefik ──"is this user allowed?"──▶ Authelia
│ │
│◀──────── 200 OK or redirect to login ─────┘
▼
protected app
- A request for
grafana.example.comhits the proxy. - The proxy makes a sub-request to Authelia.
- Not logged in: redirect to
auth.example.com, with login plus 2FA. - Logged in, and the rules allow it: the request goes through, with user and group headers available to the app.
Requirements
- Docker. See install Docker.
- All protected apps under one parent domain (
*.example.com), since session cookies are per domain. - HTTPS everywhere.
- Redis (recommended for sessions), and SMTP for password reset and 2FA enrolment emails.
Docker Compose
# /opt/authelia/compose.yaml
services:
authelia:
image: authelia/authelia:4
restart: unless-stopped
volumes:
- ./config:/config
ports:
- "127.0.0.1:9091:9091"
environment:
TZ: Etc/UTC
redis:
image: redis:7-alpine
restart: unless-stopped
Configuration
./config/configuration.yml (essentials, for version 4.38+ syntax):
server:
address: 'tcp://:9091'
log:
level: info
identity_validation:
reset_password:
jwt_secret: '<long-random>'
authentication_backend:
file:
path: /config/users_database.yml
password:
algorithm: argon2
session:
secret: '<long-random>'
cookies:
- domain: 'example.com'
authelia_url: 'https://auth.example.com'
default_redirection_url: 'https://home.example.com'
redis:
host: redis
port: 6379
storage:
encryption_key: '<long-random-at-least-20-chars>'
local:
path: /config/db.sqlite3
notifier:
smtp:
address: 'submission://smtp.example.com:587'
username: '[email protected]'
password: '<smtp-password>'
sender: 'Authelia <[email protected]>'
totp:
issuer: example.com
access_control:
default_policy: deny
rules:
- domain: 'home.example.com'
policy: one_factor
- domain: ['grafana.example.com', 'portainer.example.com']
subject: 'group:admins'
policy: two_factor
- domain: '*.example.com'
policy: two_factor
Generate secrets with openssl rand -hex 64. Better still, provide them as files via AUTHELIA_*_FILE environment variables, instead of in the YAML. See secrets management.
Users file (users_database.yml):
users:
alice:
displayname: 'Alice'
password: '$argon2id$v=19$m=65536,t=3,p=4$…'
email: [email protected]
groups: [admins]
Create password hashes with docker run --rm authelia/authelia:4 authelia crypto hash generate argon2 --password 'secret'. For larger setups, use LDAP as the backend. See OpenLDAP.
Nginx integration
Authelia’s documentation provides ready-made snippets (authelia-location.conf and authelia-authrequest.conf). The pattern, for each protected site:
server {
server_name grafana.example.com;
include /etc/nginx/snippets/authelia-location.conf; # internal /internal/authelia/authz location
location / {
include /etc/nginx/snippets/authelia-authrequest.conf; # auth_request + redirect on 401
proxy_pass http://127.0.0.1:3001;
}
# listen 443 ssl; certificates via certbot
}
And a normal reverse proxy server block for auth.example.com → 127.0.0.1:9091. Traefik uses a forwardAuth middleware, and Caddy uses forward_auth. See Nginx reverse proxy.
Second factors
Users enrol on first login at auth.example.com:
- TOTP apps (Aegis, 2FAS, Google Authenticator, Bitwarden);
- WebAuthn / passkeys (YubiKeys, platform authenticators), the strongest option;
- Duo push (optional).
OIDC provider
Authelia can also be an OpenID Connect provider, so apps with native SSO support (Gitea/Forgejo, Nextcloud, Grafana, Outline, Portainer…) log users in via Authelia. Configure identity_providers.oidc with clients, and their redirect URIs. See OAuth 2.0 and OIDC.
Tips
- Start with
default_policy: deny, and allow explicitly. - Exempt API paths and webhooks that machines call (with
policy: bypassplus network restrictions, or app tokens). - Regulation (lockout after failed attempts) is enabled by default. Tune it in
regulation:. - Back up
./config(database, users file and config), and keep it secret.
Quick reference
| Item | Value |
|---|---|
| Portal | https://auth.example.com (port 9091) |
| Policies | bypass, one_factor, two_factor, deny |
| Users | file (argon2 hashes) or LDAP |
| 2FA | TOTP, WebAuthn/passkeys, Duo |
| Proxy integration | Nginx auth_request, Traefik forwardAuth, Caddy forward_auth |
Related: Keycloak and zero trust networking.