Previously every example.com had to be found and replaced manually.
Now a single DOMAIN=yourdomain.com in .env propagates everywhere:
- .env.example: add DOMAIN=example.com with explanation
- docker-compose.yml: pass DOMAIN into authelia container environment
- authelia/configuration.yml: use {{ env "DOMAIN" }} in totp.issuer,
access_control.rules, and all four session.cookies[] fields
(Authelia 4.38+ Go template substitution)
- caddy/Caddyfile: use {env.DOMAIN} in all site block addresses
(Caddy native env substitution); update header comment explaining
how to set DOMAIN for system vs dockerized Caddy
- README.md: update step 3 to explain DOMAIN is the only change needed;
update step 4 to say just uncomment the right rule; update Caddy
wiring section with DOMAIN env var instructions for both Caddy modes
https://claude.ai/code/session_012eTokAaGiZo7aGt1T2W9BC
171 lines
6.3 KiB
YAML
171 lines
6.3 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.
|
|
# The Pi doorbell PTT page has no built-in authentication.
|
|
# two_factor is appropriate -- this URL controls a speaker in your house.
|
|
# -------------------------------------------------------------------
|
|
# - domain: 'doorbell.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# -------------------------------------------------------------------
|
|
# CASE 2: App supports trusted-header proxy auth -- replace app login.
|
|
# Frigate: set auth.enabled: False and configure proxy: in
|
|
# frigate_config/config.yml (see README.md). Authelia handles login
|
|
# and passes Remote-User/Remote-Groups to Frigate for role mapping.
|
|
# -------------------------------------------------------------------
|
|
# - domain: 'cam.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# -------------------------------------------------------------------
|
|
# CASE 3: App keeps its own auth; Authelia adds a 2FA gate in front.
|
|
# User authenticates with Authelia (2FA) then with the app itself.
|
|
# Add entries for any extra-gated domains here.
|
|
# -------------------------------------------------------------------
|
|
# - domain: 'nas.{{ env "DOMAIN" }}'
|
|
# policy: 'two_factor'
|
|
|
|
# CASE 4: No rule here, no `import authelia` in Caddy. App handles auth.
|
|
|
|
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'
|