Authelia
Authelia puts a login with two-factor authentication in front of services that have none of their own, or whose own you would rather not expose. Traefik asks Authelia through forward-auth whether a request may pass; the application behind it needs no identity integration and receives the signed-in user as request headers. Users and access rules are edited in files — there is no admin interface. Three containers: the portal, PostgreSQL for second factors, Redis for sessions.
Last run on a host 8 Nov 2026
Pinned at 4.39.28 (released 17 Sept 2026) · the newest upstream release
In the upstream images: 1 CRITICAL · 26 HIGH with a published fix — per image
To try it: Docker, nothing else. See Try it locally.
To deploy it behind the proxy: Traefik running, a domain whose parent covers the portal and every app it protects, and SMTP for one-time codes once there is more than one user.
Try it locally
Section titled “Try it locally”Authelia refuses a portal without HTTPS and a session cookie on a bare
localhost. The local stack therefore serves TLS itself, with a certificate
ops/init.sh --local creates, under auth.example.localhost — browsers resolve
.localhost names to 127.0.0.1 on their own. One container, with SQLite and
sessions in memory. From core/authelia/:
cp .env.local.example .env.localfor v in JWT_SECRET SESSION_SECRET STORAGE_ENCRYPTION_KEY; do echo "$v=$(openssl rand -hex 64)"; done >> .env.localops/init.sh --localdocker compose -f docker-compose.local.yml --env-file .env.local up -dOpen https://auth.example.localhost:9091, accept the self-signed certificate
and sign in as admin with the password in volumes/local/admin_pwd.txt.
Registering a second factor asks for a one-time code, which the local stack writes
to volumes/local/data/notification.txt. Stop it again with the same command and
down.
Installation
Section titled “Installation”From core/authelia/:
-
Copy the environment file:
Terminal window cp .env.example .envVariable What it is APP_TRAEFIK_HOSTthe portal, e.g. auth.example.comSESSION_COOKIE_DOMAINthe parent of the portal and of every protected app — example.comforauth.example.comandwiki.example.comSMTP_ADDRESS,SMTP_USERNAME,SMTP_FROM_*the relay for one-time codes and reset links TZthe timezone in the logs Apps on another domain cannot share the sign-in. Without
SMTP_ADDRESS, codes and reset links go tovolumes/data/notification.txt— enough for one administrator. -
Create the secrets, the data directories and the first user:
Terminal window ops/init.sh # user admin; or: ops/init.sh <name> <email>Authelia generates the first user’s password and its Argon2 hash; the password goes to
.secrets/admin_pwd.txtand never appears on a command line. The script sets ownership with a throwaway container, so nosudois needed. Running it again overwrites nothing. With a relay, write its password to.secrets/smtp_password.txt. -
List
authelia-edgeinEDGE_NETWORKSincore/traefik/.env, then render and restart Traefik — see edge networks. -
Start it:
Terminal window docker compose up -d -
Open
https://<APP_TRAEFIK_HOST>, sign in asadminand register a second factor — TOTP or a security key.
Verify
Section titled “Verify”docker compose ps # three services, healthydocker compose logs authelia | grep -i "startup complete"Then protect one application as below and open it: the browser goes to the portal and comes back signed in.
Putting a login in front of a service
Section titled “Putting a login in front of a service”-
Define the middleware once, in a file under
core/traefik/config/dynamic/— Traefik reloads it on its own:http:middlewares:authelia:forwardAuth:address: "http://authelia-app:9091/api/authz/forward-auth"authResponseHeaders:- Remote-User- Remote-Groups- Remote-Email- Remote-NameTraefik makes this call itself and reaches
authelia-appover Authelia’s edge network.trustForwardHeaderstays unset, so Authelia sees the headers Traefik built, not ones a client supplied. -
In the
.envof the stack to protect, put the middleware in the auth position, thendocker compose up -dthere:APP_TRAEFIK_AUTH=authelia@file -
Decide who may enter, in
config/configuration.yml. The shipped rule requires two factors on every host underSESSION_COOKIE_DOMAINand denies everything else. Rules are read top to bottom and the first match wins, so a rule for one app goes above the wildcard:access_control:default_policy: 'deny'rules:- domain: 'wiki.example.com'subject: 'group:admins'policy: 'two_factor'- domain: '*.example.com'policy: 'two_factor'
Going further
Section titled “Going further”Who can reach the portal
Section titled “Who can reach the portal”The portal ships access-vpn, with limit-standard and headers-standard, like
the apps behind it. A public app needs a public login page: once one protected
app is access-public, set the portal to access-public as well.
Users live in volumes/data/users_database.yml, with their password hashes.
Add one by generating a hash and adding an entry:
docker run --rm authelia/authelia:<APP_TAG> authelia crypto hash generate argon2 --random --random.length 32The output carries the password, shown once, and its digest for the password:
field.
Choosing between Authelia, Authentik and Keycloak
Section titled “Choosing between Authelia, Authentik and Keycloak”| Authelia | Authentik | Keycloak | |
|---|---|---|---|
| Built around | forward-auth for a reverse proxy | identity provider with flows and outposts | realms, clients, federation |
| Users and rules | YAML files | web interface | web interface |
| Protocols to apps | headers through the proxy | forward-auth, OIDC, SAML, LDAP, RADIUS | OIDC, SAML, LDAP federation |
Hardening
Section titled “Hardening”The container runs read-only, as 1000:1000, with no capabilities. Secrets reach
Authelia through its _FILE variables. Authelia rewrites
/app/.healthcheck.env at every start, so that one file is mounted writable.
Backup
Section titled “Backup”| Database | PostgreSQL, container authelia-db, database authelia, user authelia — second factors, per-user settings, sign-in history |
| Password | .secrets/db_pwd.txt |
| Also needed | volumes/data/users_database.yml (users and hashes) · .secrets/storage_encryption_key.txt |
| Rebuildable | volumes/redis (sessions — users sign in again) · volumes/runtime |
For borgmatic:
postgresql_databases: - name: authelia username: authelia pg_dump_command: docker exec authelia-db pg_dump pg_restore_command: docker exec -i authelia-db pg_restore psql_command: docker exec -i authelia-db psqlThe dump is useless without storage_encryption_key.txt. It encrypts the
second factors in the database; without it every user registers TOTP and
security keys again. Keep .secrets/ in the same backup.
Restore order: database, users file and secrets, then the containers. Authelia migrates the schema at start and refuses a schema newer than its own version.
Updates
Section titled “Updates”Configuration keys are renamed between minor versions, and the old names are removed after a deprecation period.
-
Read the release notes.
-
Raise
APP_TAGin.envand check the configuration against the new version:Terminal window docker compose run --rm --no-deps authelia authelia validate-config --config /config/configuration.yml -
Back up the database,
volumes/dataand.secrets/. -
Terminal window docker compose pull && docker compose up -d -
Sign in through a protected app.
Troubleshooting
Section titled “Troubleshooting”Every protected app answers 403 or loops back to the portal. The host is not
covered by a rule in access_control, or it is not under
SESSION_COOKIE_DOMAIN, so the cookie does not reach it.
Authelia refuses to start, naming an unknown setting. Authelia reads every
AUTHELIA_* environment variable as a setting. Configuration keys renamed in a
new version do the same — run validate-config.
No one-time code arrives. SMTP_ADDRESS is empty, so codes are written to
volumes/data/notification.txt.
Users have to register their second factor again after a restore.
storage_encryption_key.txt was not restored with the database.
Repository files
Section titled “Repository files”core/authelia/README.md— architecture, protecting an app, security modelcore/authelia/config/configuration.yml— access rules and settingscore/authelia/ops/init.sh— secrets, directories and the first usercore/authelia/.env.examplecore/authelia/UPSTREAM.md— upgrade checklist
Official sources
Section titled “Official sources”© 2026 SecDockBlueCode Apache-2.0Site content CC BY-NC 4.0