-
Notifications
You must be signed in to change notification settings - Fork 1
Authentication
Note
Source: roles/authelia/ in the
SEEDbox repo. The middleware
assignments below come from the Traefik labels each role sets on its own container.
- Overview
- The three groups
- How Authelia is wired into Traefik
- Users
- Access control policy
- Sessions and brute force protection
- Two factor authentication
- Password reset and notifications
- Storage and secrets
- Things worth knowing
Authelia is the single sign-on portal for the stack. It runs as a forward-auth provider behind Traefik: Traefik asks Authelia whether a request is allowed before it ever reaches the application.
It is published on login.yourdomain.com by default (authelia.subdomain in settings.yml).
Important
Authelia does not sit in front of every application. Eight services are published with no Authelia middleware and are protected only by their own login page. Know which group each of your services is in before you expose anything.
The router carries the forward-auth middleware. An unauthenticated request is redirected to the Authelia portal, and the application is never reached until login succeeds.
| ArchiveBox | Bazarr | Flood | Librespeed |
| Lidarr | Netdata | NZBGet | Prowlarr |
| qBittorrent | Radarr | Readarr | ruTorrent |
| SABnzbd | Scrutiny | Sonarr | Speedtest Tracker |
| Syncthing | Traefik | whoami |
Same check, but Authelia answers with an HTTP basic auth challenge rather than a redirect to the portal. Used by Homer only, because the dashboard is fetched as a static page and a redirect would break it.
No Authelia middleware. These applications are reachable directly and their own login page is the only thing protecting them.
| Application | Why |
|---|---|
| Portainer | Has its own user database and API tokens |
| qui | Has its own login |
| Seerr | Uses Jellyfin or a local account, and needs its API reachable |
| Jellyfin | Client apps cannot complete a forward-auth redirect |
| Navidrome | Subsonic clients cannot complete a forward-auth redirect |
| Kavita | Reader apps and OPDS feeds cannot complete a forward-auth redirect |
| Yamtrack | Has its own Django account system |
| File Browser | Has its own user database |
Warning
Several of these applications create their admin account on first visit, meaning whoever reaches the URL first claims it. The Kavita and Yamtrack roles close that window by registering the admin over the API during the play. For the rest, log in and set your password immediately after the first deploy.
The authelia role defines both middlewares as labels on its own container:
| Middleware | Address | Behaviour |
|---|---|---|
authelia@docker |
http://authelia:9091/api/verify?rd=https://login.yourdomain.com/ |
Redirects to the portal |
authelia-basic@docker |
http://authelia:9091/api/verify?auth=basic |
HTTP basic auth challenge |
Both set trustForwardHeader: true. A role opts in by setting one label on its own router:
traefik.http.routers.<service>.middlewares: "authelia@docker"That single line is the whole difference between the first group and the third. To put an app from the Built-in group behind Authelia, add the label to that role and redeploy.
Users live in a flat file, {{ authelia.folder }}/users_database.yml, generated from
settings.yml:
| Setting | Purpose |
|---|---|
authelia.username |
Login name |
authelia.password |
Plaintext in settings.yml, hashed into the file with sha512crypt at 50000 rounds |
authelia.displayname |
Shown in the portal |
authelia.email |
Used for password reset and notifications |
The generated user belongs to the admins and dev groups.
Warning
The role writes this file with force: true, so it is overwritten on every playbook run. Any
user you add by hand is lost the next time you deploy. Add users to the template, not to the file
on disk.
The hash is also re-salted on every run, so the file shows as changed on each deploy even when nothing in your settings did.
access_control:
default_policy: deny
rules:
- domain: yourdomain.com
policy: one_factor
- domain: "*.yourdomain.com"
policy: one_factorThe default is deny, and the two rules bring the apex domain and every subdomain up to
one_factor. In practice: one factor, username and password, everywhere. Anything outside your
domain is denied.
To require 2FA on a specific service, add a rule above the wildcard:
- domain: qbittorrent.yourdomain.com
policy: two_factorRules are evaluated in order, so a more specific rule must come first.
| Setting | Value | Meaning |
|---|---|---|
session.expiration |
3600 | Session is valid for 1 hour |
session.inactivity |
300 | Idle for 5 minutes and you re-authenticate |
session.domain |
your domain | The session cookie is shared across every subdomain, so one login covers the whole stack |
regulation.max_retries |
3 | Failed logins before a ban |
regulation.find_time |
120 | Window in seconds those 3 failures must fall within |
regulation.ban_time |
300 | Ban length in seconds |
Sessions are stored in the authelia-redis container, so a restart of Authelia does not log
everyone out.
Tip
A 5 minute inactivity window is aggressive for a media stack. Raise inactivity in
roles/authelia/templates/configuration.yml.j2 if you are tired of re-authenticating.
TOTP is configured with your domain as the issuer, so you can enrol an authenticator app from the
Authelia portal. But because the access control policy is one_factor everywhere, enrolling does
not by itself cause 2FA to be requested. You must also raise the policy to two_factor for the
domains you want protected.
Duo push is present in the template but commented out.
Password reset is enabled and delivers over SMTP through the postfix container:
| Setting | Source |
|---|---|
notifier.smtp.host |
authelia.notification_email_server, default postfix
|
notifier.smtp.port |
authelia.notification_email_server_port, default 587 |
notifier.smtp.sender |
authelia.notification_email_from |
disable_startup_check: true and disable_require_tls: true are set, the latter because the hop to
the local postfix container is on the internal Docker network.
Authelia keeps its own database at /config/db.sqlite3 inside the container, encrypted with
authelia.storage_encryption_key.
Important
Three values in settings.yml must be changed from their defaults before you expose anything:
| Setting | Requirement |
|---|---|
authelia.jwt_secret |
Long random string, signs the identity tokens |
authelia.unsecure_session_secret |
Long random string, signs the session cookie |
authelia.storage_encryption_key |
At least 64 characters, Authelia refuses to start otherwise |
Generate them with something like openssl rand -hex 32 (use -hex 64 for the storage key).
-
The config file is world readable.
configuration.ymlis written with mode0775and holds all three secrets in plaintext. Anyone with a shell on the host can read them. -
Log level is
debug. Useful while setting up, noisy in normal operation. Changelog.levelin the template toinfoonce the stack is running. - One login covers everything. Because the session cookie is scoped to the whole domain, authenticating at any one service authenticates you at all of them in the first group.
- Authelia protects Traefik's own dashboard, so losing Authelia means losing the dashboard too.
Install
Configuration
Reference
Help