Authelia is an authentication and authorization server your reverse proxy consults before it lets a request through, with two-factor, per-path access rules and an OpenID Connect provider. It replaces per-app login screens and hosted access gateways like Cloudflare Access or Duo.
Our verdict on Authelia#
Authelia has never shipped a 1.0. It is on 4.39.22 as of September 2026 and that number is a leftover from 2019 rather than a beta warning: the forward-auth half has been dependable for years. The OIDC provider is a different story. It is OpenID Certified, but the project still labels it beta, currently Beta 8 targeted at 4.40.0, and it has shipped breaking changes inside minor releases. Be clear about what forward auth buys you. Authelia gates the HTTP request, it does not log you into the app behind it. Unless that app reads Remote-User and Remote-Groups headers, your users authenticate at Authelia, pass, then meet a second login form. And anything that is not a browser (mobile apps, WebDAV clients, API tokens, Jellyfin on a TV) needs a bypass rule, which is exactly where the protection you thought you added quietly leaks away.
Who Authelia is for#
Choose it if
- You already run Traefik, Caddy or nginx and want a single 2FA gate in front of a dozen apps that have no authentication of their own.
- You want an OIDC issuer that fits in 40 MB and one config file rather than a three-container identity stack.
- You already have LLDAP or OpenLDAP and want a login portal, password reset and TOTP enrollment on top of it.
- Single-host homelabs where a stateless Go binary is worth more than a feature matrix.
Look elsewhere if
- Your users are mobile-first. Forward auth and native mobile clients do not mix, and the bypass rules you write to fix it undo most of the protection.
- You need a SAML identity provider. Authelia does not ship one.
- You want user self-registration, SCIM provisioning or an admin UI for managing accounts. There is none; you edit YAML or manage the directory somewhere else.
What running it actually looks like#
One container, one configuration.yml, and four secrets you generate yourself: session secret, storage encryption key, storage password and the identity validation JWT secret. Before it will start you need a user source (a users_database.yml of Argon2id hashes from authelia crypto hash generate argon2, or an LDAP bind) and a notifier (SMTP, or the file notifier that writes reset links to disk for testing). It listens on 9091. The real work is in the proxy: nginx calls /api/authz/auth-request, Traefik, Caddy and HAProxy call /api/authz/forward-auth, Envoy calls /api/authz/ext-authz. Storage defaults to SQLite and sessions default to in-memory, so every restart signs everyone out until you add Redis. Access control rules are ordered and first match wins, which is how most people put a bypass above a two_factor by accident.
Resource profile#
- Memory
- 35 MB idle, around 80 MB in ordinary use. A single Go binary serving an embedded React bundle. Estimated range of 30 to 60 MB idle from typical installs; the project publishes no official figure. Adding Redis roughly doubles the footprint.
- CPU and acceleration
- Near zero between logins. Argon2id password hashing is the only meaningful cost and it is tuned to be slow on purpose, so a burst of simultaneous logins on a low-power ARM board is noticeable.
- Storage growth
- Tiny. The database holds TOTP secrets, WebAuthn credentials, OIDC consent grants and issued tokens, measured in kilobytes per user. The regulation and audit tables are the only things that grow.
- Operational load
- 3 of 5, Moderate. One service, but its config is a large YAML file coupled tightly to your reverse proxy, and 4.38 rewrote both the session block and the proxy endpoints. Restores need the storage encryption key as well as the database, in that order.
Figures describe a small single-household install and are the working assumptions behind our stack planner. Your numbers will differ with library size, user count and hardware. See methodology.
Data and backup surface#
Three things matter and only one is a database. configuration.yml plus the secret files are configuration; keep them wherever you keep infrastructure state. The storage backend (db.sqlite3 by default) holds TOTP secrets, registered WebAuthn credentials, OIDC consent grants and issued tokens, and the sensitive columns are encrypted with storage.encryption_key. Back that key up separately from the database and understand what losing it means: every user re-enrolls their authenticator app and security keys. There is an authelia storage encryption change-key command, but it needs the old key. If you use the file backend, users_database.yml holds the password hashes. Nothing here is large, so a nightly copy of a stopped instance is adequate.
Derived backup shape
SQLite backup. sqlite3 <db> ".backup out.db" while running, or stop the container and copy. A live cp of a WAL-mode SQLite file can restore corrupt.
Traps and surprises#
The 4.38 configuration break
Upgrading from 4.37 or earlier is a rewrite, not a tag bump. session.domain and default_redirection_url moved into a session.cookies array, remember_me_duration became remember_me, a new mandatory authelia_url appeared, the OIDC issuer_private_key became a jwks array, and /api/verify was replaced by per-proxy endpoints with the rd parameter removed. Your proxy snippet has to change at the same time.
In-memory sessions are the default
The memory session provider is the default and it is stateful in the running process. Every container restart, every image pull, every host reboot signs out every user, including anyone mid-way through TOTP enrollment. That is fine for a home instance and infuriating for anyone else. The fix is a Redis container, which turns your single-container deployment into two.
Losing storage.encryption_key is unrecoverable
Sensitive columns are encrypted at the application layer with a key that lives in your config, not in the database. Restore a database dump onto an instance with a different key and every TOTP secret and WebAuthn credential in it is garbage: users must re-enroll from scratch. Store the key with the backup but not inside it, and rotate only with authelia storage encryption change-key while you still have the old value.
Cookie domains and the Public Suffix List
Authelia's session cookie has to be set on a domain that is a parent of every protected app. Browsers enforce the Public Suffix List, so you cannot share a cookie between example.duckdns.org and example-auth.duckdns.org, and localhost will not work either. If you are on a free dynamic DNS subdomain, this is the wall you hit first. You need a registrable domain of your own.
Bypass rules are where the security leaks
Forward auth is all or nothing per path, so anything without a browser needs an exception: /api/ for a mobile app, /remote.php/dav for Nextcloud clients, whole subdomains for Jellyfin. Every policy: bypass you add is an unauthenticated hole, and because rules are first-match-wins, one placed too high silently disables two-factor for everything below it. Audit the rule list, not just the last rule you added.
Specifications#
- Category
- Passwords, SSO and identity
- Licence
- Apache-2.0 (Permissive)
- Written in
- Go / TypeScript
- First release
- 2017
- Maturity
- Stable
- Datastore
- SQLite (default), PostgreSQL or MySQL; sessions in memory or Redis
- Default ports
9091- Ships as
- docker, native binary, deb/rpm package, helm chart
- arm64 builds
- Yes
- Identity
- LDAP only. Authelia is the identity provider; its own user source is a YAML file of Argon2id hashes or an LDAP directory, and it cannot federate up to an external OIDC or social provider.
- Replaces
- Cloudflare Access, Okta, Duo Security, Auth0
- Project site
- www.authelia.com
- Source
- github.com/authelia/authelia
- Documentation
- www.authelia.com/configuration/prologue/introduction
Alternatives to Authelia#
Everything else in passwords, sso and identity, closest in operational weight first.
| Tool | Ops load | Idle RAM | Licence |
|---|---|---|---|
| Keycloak | 4, Heavy | 750 MB | Apache-2.0 |
| Vaultwarden | 2, Light | 40 MB | AGPL-3.0 |
| authentik | 4, Heavy | 1000 MB | MIT (core); authentik/enterprise/ under a separate Authentik Security license |
| LLDAP | 1, Set and forget | 15 MB | GPL-3.0 |
| Pocket ID | 1, Set and forget | 30 MB | BSD-2-Clause |
Where Authelia comes up elsewhere#
Head to head
Guides
Research
Calculators
Sources#
Facts on this page were checked against the project's own material. Where a number is our own estimate rather than a published figure, the text says so.
Published . Last reviewed . Found something out of date? Tell us and we will fix it and log the change.