Each of the four cases in access_control.rules now carries an inline,
clearly-labeled "ALSO PASTE INTO CADDYFILE" block above the
uncommentable Authelia rule, so the user editing configuration.yml
sees both halves of the gate in one place. Case 2a additionally shows
the matching frigate_config/config.yml edit; case 4 has no Authelia
rule but still shows the Caddy block to make the absence explicit.
Caddy blocks use {env.DOMAIN}, Authelia rules use {{ env "DOMAIN" }} --
matching what's already in caddy/snippets.caddyfile and the
configuration.yml header.
https://claude.ai/code/session_013XZ1vmgk78k2PEQ5DmJhF3
242 lines
9.1 KiB
YAML
242 lines
9.1 KiB
YAML
---
|
|
###############################################################################
|
|
# Authelia configuration
|
|
#
|
|
# - File-based user database (no LDAP)
|
|
# - SQLite local storage (no Redis, no MySQL/Postgres)
|
|
# - Filesystem notifier (writes "emails" to /config/notifications/...)
|
|
# - Argon2id password hashing
|
|
# - Per-domain access policies under access_control.rules
|
|
#
|
|
# Secrets are NOT in this file. They are loaded from files mounted at
|
|
# /secrets via the AUTHELIA_*_FILE env vars in docker-compose.yml.
|
|
#
|
|
# Your domain comes from the DOMAIN variable in .env -- no manual
|
|
# find-and-replace needed. Authelia 4.38+ processes this file as a Go
|
|
# template, so {{ env "DOMAIN" }} is substituted at startup.
|
|
#
|
|
# After editing, validate before restarting:
|
|
# docker compose run --rm authelia authelia validate-config --config /config/configuration.yml
|
|
###############################################################################
|
|
|
|
theme: 'dark'
|
|
|
|
server:
|
|
address: 'tcp://0.0.0.0:9091'
|
|
buffers:
|
|
read: 8192
|
|
write: 8192
|
|
|
|
log:
|
|
level: 'info'
|
|
format: 'text' # fail2ban filter expects text format -- don't change to json
|
|
file_path: '/config/authelia.log'
|
|
keep_stdout: true # also log to stdout for `docker logs`
|
|
|
|
identity_validation:
|
|
reset_password:
|
|
jwt_lifespan: '5 minutes'
|
|
jwt_algorithm: 'HS256'
|
|
# jwt_secret loaded via AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE
|
|
|
|
totp:
|
|
disable: false
|
|
issuer: '{{ env "DOMAIN" }}' # shown in your authenticator app
|
|
algorithm: 'sha1'
|
|
digits: 6
|
|
period: 30
|
|
|
|
authentication_backend:
|
|
password_change:
|
|
disable: false
|
|
password_reset:
|
|
disable: false
|
|
refresh_interval: '5 minutes'
|
|
file:
|
|
path: '/config/users_database.yml'
|
|
password:
|
|
algorithm: 'argon2'
|
|
argon2:
|
|
variant: 'argon2id'
|
|
iterations: 3
|
|
memory: 65536
|
|
parallelism: 4
|
|
key_length: 32
|
|
salt_length: 16
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Access control
|
|
#
|
|
# default_policy: deny -- every domain Caddy forward_auths here must have
|
|
# an explicit rule. Domains with no `import authelia` in Caddy never reach
|
|
# Authelia at all, so the deny doesn't apply to them.
|
|
#
|
|
# Policies:
|
|
# bypass Authelia waves the request through (used for the portal)
|
|
# one_factor password only
|
|
# two_factor password + TOTP
|
|
#
|
|
# ---------------------------------------------------------------------------
|
|
# WHICH SITES NEED A RULE HERE?
|
|
#
|
|
# CASE 1 -- App has NO built-in auth (e.g. Pi doorbell PTT page).
|
|
# -> Rule required + `import authelia` in Caddy.
|
|
# -> Authelia is the ONLY login. Use two_factor for hardware-control pages.
|
|
#
|
|
# CASE 2 -- App has built-in auth AND supports trusted-header proxy auth
|
|
# (Frigate 0.14+, Grafana, Gitea, Nextcloud, Home Assistant ...).
|
|
# -> Rule required + `import authelia` in Caddy + disable the app's login
|
|
# form in its own config (see README.md per-app instructions).
|
|
# -> Single Authelia login covers both access AND the app's user/role
|
|
# mapping via Remote-User / Remote-Groups headers.
|
|
#
|
|
# CASE 3 -- App has built-in auth and CANNOT switch to proxy auth, but you
|
|
# still want a 2FA gate in front of it (extra security layer).
|
|
# -> Rule required + `import authelia` in Caddy.
|
|
# -> User logs into Authelia (2FA) THEN into the app's own login form.
|
|
# Two separate logins -- the app auth is unchanged.
|
|
# -> Useful for: router admin pages, NAS UIs, any legacy app.
|
|
#
|
|
# CASE 4 -- App handles its own auth and you don't want Authelia involved.
|
|
# -> NO rule here + NO `import authelia` in Caddy.
|
|
# -> Traffic skips Authelia entirely; the app handles everything.
|
|
# ---------------------------------------------------------------------------
|
|
access_control:
|
|
default_policy: 'deny'
|
|
rules:
|
|
|
|
# The Authelia portal itself is always bypass.
|
|
- domain: 'auth.{{ env "DOMAIN" }}'
|
|
policy: 'bypass'
|
|
|
|
# ===================================================================
|
|
# CASE 1 -- No app auth. Authelia is the only gate.
|
|
# Example: Pi doorbell PTT page (Flask server, no built-in auth).
|
|
# two_factor is right -- this URL controls a speaker in your house.
|
|
#
|
|
# ALSO PASTE INTO CADDYFILE (case 1 site block):
|
|
# doorbell.{env.DOMAIN} {
|
|
# import accesslog
|
|
# import authelia
|
|
# handle_path /frigate/* {
|
|
# reverse_proxy 192.168.x.x:8971 # CHANGE: Frigate IP
|
|
# }
|
|
# handle {
|
|
# reverse_proxy 192.168.x.x:5555 # CHANGE: Pi IP
|
|
# }
|
|
# }
|
|
# ===================================================================
|
|
# - domain: 'doorbell.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# ===================================================================
|
|
# CASE 2a -- App supports trusted-header proxy auth.
|
|
# Authelia replaces the app's login form. Single login; the app reads
|
|
# Remote-User from the upstream request for its own role mapping.
|
|
# Example: Frigate 0.14+.
|
|
#
|
|
# ALSO PASTE INTO CADDYFILE (case 2a site block):
|
|
# cam.{env.DOMAIN} {
|
|
# import accesslog
|
|
# import authelia
|
|
# reverse_proxy 192.168.x.x:8971 { # CHANGE: Frigate IP
|
|
# transport http { read_timeout 60s; write_timeout 60s }
|
|
# # header_up X-Proxy-Secret "32-byte-hex" # if Frigate auth_secret set
|
|
# }
|
|
# }
|
|
#
|
|
# ALSO EDIT frigate_config/config.yml IN THE FRIGATE REPO:
|
|
# auth:
|
|
# enabled: False
|
|
# trusted_proxies: [172.18.0.0/16] # caddy_net subnet
|
|
# proxy:
|
|
# header_map: {user: remote-user, role: remote-groups}
|
|
# default_role: viewer
|
|
# separator: '|'
|
|
# ===================================================================
|
|
# - domain: 'cam.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# ===================================================================
|
|
# CASE 2b -- App supports OIDC. Authelia is the OIDC provider.
|
|
# Caddy block is identical to case 2a; the difference is on the app
|
|
# side (token exchange, not header). REQUIRES additional setup of
|
|
# identity_providers.oidc below this access_control block, with one
|
|
# client per app -- see Authelia OIDC docs.
|
|
# Example: Audiobookshelf.
|
|
#
|
|
# ALSO PASTE INTO CADDYFILE (case 2b site block):
|
|
# books.{env.DOMAIN} {
|
|
# import accesslog
|
|
# import authelia
|
|
# reverse_proxy 192.168.x.x:13378 # CHANGE IP
|
|
# }
|
|
# ===================================================================
|
|
# - domain: 'books.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# ===================================================================
|
|
# CASE 3 -- App keeps its own login. Authelia adds a 2FA gate in
|
|
# front. User authenticates with Authelia (2FA), then with the app
|
|
# itself. Two logins, but Authelia's 2FA covers apps that don't
|
|
# support proxy headers OR OIDC OR native TOTP.
|
|
# Example: Uptime Kuma, Portainer (without OIDC), router admin.
|
|
#
|
|
# ALSO PASTE INTO CADDYFILE (case 3 site block):
|
|
# uptime.{env.DOMAIN} {
|
|
# import accesslog
|
|
# import authelia
|
|
# reverse_proxy 192.168.x.x:3001 # CHANGE IP
|
|
# }
|
|
# ===================================================================
|
|
# - domain: 'uptime.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# ===================================================================
|
|
# CASE 4 -- App handles its own auth. NO rule needed here.
|
|
# Authelia is never consulted. Caddy still imports accesslog so
|
|
# fail2ban watches the subdomain for scanners.
|
|
# Example: Plex/Emby (native clients break with Authelia redirects),
|
|
# Syncthing, anything you've decided to leave alone.
|
|
#
|
|
# ONLY PASTE INTO CADDYFILE -- nothing here in configuration.yml:
|
|
# plex.{env.DOMAIN} {
|
|
# import accesslog # NO import authelia
|
|
# reverse_proxy 192.168.x.x:32400 # CHANGE IP
|
|
# }
|
|
# ===================================================================
|
|
# (no rule -- case 4 is the absence of one)
|
|
|
|
session:
|
|
# secret loaded via AUTHELIA_SESSION_SECRET_FILE
|
|
cookies:
|
|
- name: 'authelia_session'
|
|
domain: '{{ env "DOMAIN" }}'
|
|
authelia_url: 'https://auth.{{ env "DOMAIN" }}'
|
|
default_redirection_url: 'https://{{ env "DOMAIN" }}'
|
|
expiration: '1 hour'
|
|
inactivity: '5 minutes'
|
|
remember_me: '1 month'
|
|
same_site: 'lax'
|
|
|
|
# In-app rate limiting. Locks the user account after repeated failures.
|
|
# fail2ban is the second line of defense: it bans the source IP.
|
|
# Together: Authelia locks the *user*, fail2ban bans the *IP*.
|
|
regulation:
|
|
max_retries: 3
|
|
find_time: '2 minutes'
|
|
ban_time: '5 minutes'
|
|
|
|
storage:
|
|
# encryption_key loaded via AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE
|
|
local:
|
|
path: '/config/db.sqlite3'
|
|
|
|
# Filesystem notifier -- password reset / new device emails get written to
|
|
# a file you can `tail -f`. Swap to `smtp:` when you wire up a real
|
|
# transactional sender (see README.md "Switching the notifier to SMTP").
|
|
notifier:
|
|
disable_startup_check: false
|
|
filesystem:
|
|
filename: '/config/notifications/notification.txt'
|