适用场景:个人服务器、Authelia 以 Docker 部署、Caddy 以系统服务方式安装
示例域名:auth.demo.com(Authelia)、wud.demo.com(受保护应用)
1. 架构说明
宿主机(Caddy 以 systemd 服务运行)
├── 监听 80/443,自动 HTTPS
├── 通过 127.0.0.1:9091 访问 Authelia(Docker 容器)
└── 通过 forward_auth 保护各应用域名
Docker 网络 auth-net
├── authelia(容器)
└── authelia-redis(容器)
各应用容器(可各自独立网络)
├── wud
└── homepage
2. 目录结构建议
authelia/
├── docker-compose.yml
├── .env
├── config/
│ ├── configuration.yml
│ └── users_database.yml
├── secrets/
│ ├── JWT_SECRET
│ ├── SESSION_SECRET
│ └── STORAGE_ENCRYPTION_KEY
└── redis-data/
3. 安装 Caddy
参考官方文档:caddyserver.com/docs/install
以下以 Debian / Ubuntu / Raspbian 为例。该安装方式会自动将 Caddy 注册为 systemd 服务 caddy,并随系统启动。
sudo apt install --yes debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo chmod o+r /usr/share/keyrings/caddy-stable-archive-keyring.gpg
sudo chmod o+r /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
安装完成后,Caddy 服务通常已自动启动。确认状态:
sudo systemctl status caddy
如需手动启用开机自启并立即启动:
sudo systemctl enable --now caddy
Caddyfile 位置:通过 apt 安装后,默认配置通常位于 /etc/caddy/Caddyfile。修改后重载:
sudo systemctl reload caddy
其他发行版(Fedora、RedHat、静态二进制等)的安装命令请直接参考上述官方文档页面,步骤类似,核心是让
caddy以系统服务方式运行。
4. 生成 Authelia 密钥文件
在 authelia/ 目录下执行:
mkdir -p secrets config redis-data
openssl rand -base64 48 | tr -d '=/+' | head -c 64 > secrets/JWT_SECRET
openssl rand -base64 48 | tr -d '=/+' | head -c 64 > secrets/SESSION_SECRET
openssl rand -base64 48 | tr -d '=/+' | head -c 64 > secrets/STORAGE_ENCRYPTION_KEY
chmod 600 secrets/*
三个文件内容均为随机字符串,不要加引号或换行。
5. .env 文件
# .env
TZ=Asia/Shanghai
AUTHELIA_DOMAIN=auth.demo.com
6. docker-compose.yml
services:
authelia:
image: docker.io/authelia/authelia:latest
container_name: authelia
restart: unless-stopped
ports:
# 关键:必须让宿主机上的 Caddy 能访问 9091
# 使用 127.0.0.1 绑定,仅宿主机本地可达,不暴露公网
- "127.0.0.1:9091:9091"
volumes:
- ./config:/config
- ./secrets:/secrets
environment:
TZ: ${TZ}
AUTHELIA_JWT_SECRET_FILE: /secrets/JWT_SECRET
AUTHELIA_SESSION_SECRET_FILE: /secrets/SESSION_SECRET
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /secrets/STORAGE_ENCRYPTION_KEY
networks:
- auth-net
depends_on:
- redis
redis:
image: docker.io/library/redis:alpine
container_name: authelia-redis
restart: unless-stopped
volumes:
- ./redis-data:/data
networks:
- auth-net
networks:
auth-net:
name: auth-net
driver: bridge
- 使用
_FILE环境变量从文件读取密钥,避免把密钥写进环境变量。 127.0.0.1:9091:9091确保 Authelia 不直接暴露公网。- Redis 用于 Lite 部署的会话存储,避免容器重启后登录状态丢失。
7. 用户数据库 config/users_database.yml
users:
admin:
displayname: "Admin"
password: "$argon2id$v=19$m=65536,t=3,p=4$..."
email: admin@demo.com
生成密码哈希:
docker run --rm authelia/authelia:latest \
authelia crypto hash generate argon2 --password '你的密码'
将输出的整串 $argon2id$... 替换到 password 字段。
8. config/configuration.yml
###############################################################
# Authelia configuration
###############################################################
server:
address: 'tcp://:9091'
log:
level: 'info'
authentication_backend:
file:
path: '/config/users_database.yml'
access_control:
default_policy: 'deny'
rules:
- domain: 'wud.demo.com'
policy: 'one_factor'
session:
cookies:
- name: 'authelia_session'
domain: 'demo.com' # 必须覆盖 auth.demo.com 及各应用子域
authelia_url: 'https://auth.demo.com'
expiration: '1 hour'
inactivity: '5 minutes'
redis:
host: 'authelia-redis'
port: 6379
regulation:
max_retries: 3
find_time: '2 minutes'
ban_time: '5 minutes'
storage:
local:
path: '/config/db.sqlite3'
notifier:
filesystem:
filename: '/config/notification.txt'
关键对应关系:
| 配置项 | 值 | 来源 / 说明 |
|---|---|---|
server.address |
tcp://:9091 |
容器内监听端口,与 compose 的 9091:9091对应 |
authentication_backend.file.path |
/config/users_database.yml |
即之前创建的 config/users_database.yml |
access_control |
default_policy: deny+ 显式规则 |
被列出的域名才受保护 |
session.redis.host |
authelia-redis |
与 compose 中 Redis 容器名一致 |
session.cookies.domain |
demo.com |
根域,必须覆盖 auth.demo.com 和所有受保护子域 |
storage.local.path |
/config/db.sqlite3 |
自动在 config/下生成,无需手动创建 |
notifier.filesystem.filename |
/config/notification.txt |
用于记录通知(如密码重置),必填,否则容器无法启动 |
安全提醒:session.secret 和 storage.encryption_key 不要写进这个文件,它们已经通过 compose 的 _FILE 环境变量从 secrets/ 目录注入。
9. Caddyfile 配置
Caddy 以系统服务运行,Caddyfile 默认位于 /etc/caddy/Caddyfile。修改后用 sudo systemctl reload caddy 生效。
9.1 Authelia 自身的站点
让 auth.demo.com 正常访问登录页和 API,不要加 forward_auth,否则会死循环:
auth.demo.com {
reverse_proxy 127.0.0.1:9091
}
9.2 保护 WUD
wud.demo.com {
forward_auth 127.0.0.1:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
reverse_proxy 127.0.0.1:18005
}
这里 127.0.0.1:18005 是 WUD 映射到宿主机的端口。
9.3 关键说明
forward_auth 127.0.0.1:9091:因为 Caddy 在宿主机上,直接用127.0.0.1:9091访问 Authelia,不需要容器名,不需要加入任何 Docker 网络。copy_headers:认证成功后,Authelia 返回的用户身份头部会被复制到发往后端的请求中。- 后续新增应用时,复制上面的块,替换域名和
reverse_proxy的后端地址即可。
10. 文件清单
| 文件 | 作用 |
|---|---|
docker-compose.yml |
启动 Authelia 和 Redis |
.env |
时区、域名等非敏感变量 |
config/configuration.yml |
Authelia 主配置 |
config/users_database.yml |
用户数据库 |
secrets/JWT_SECRET |
JWT 密钥 |
secrets/SESSION_SECRET |
会话密钥 |
secrets/STORAGE_ENCRYPTION_KEY |
存储加密密钥 |
/etc/caddy/Caddyfile |
Caddy 系统服务配置,含 Authelia 自身反代及各应用 forward_auth |
11. 通知器(Notifier)说明
从 Authelia v4.15.0 开始,通知器配置被纳入启动强制校验。如果不配置通知器,Authelia 容器启动时会直接报错并陷入无限重启(Restarting) 。
通知器用于发送密码重置链接、双因素认证令牌等消息。Authelia 强制要求必须且只能配置 filesystem 或 smtp 其中的一种:
11.1 文件通知器(个人服务器首选)
上文第 8 节使用的就是这种模式,它不需要外部邮件服务,直接将消息追加写入到本地文本文件。
notifier:
filesystem:
filename: '/config/notification.txt'
- 验证方法:执行
docker exec authelia authelia debug notification,然后查看config/notification.txt是否生成了新内容。
11.2 SMTP 通知器(生产环境/需要真实邮件)
如果你需要将密码重置链接发送到真实邮箱,需要替换为 SMTP 配置:
notifier:
smtp:
address: 'smtp://127.0.0.1:25'
sender: 'Authelia <admin@demo.com>'
username: 'your-smtp-username'
# 密码建议通过 AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE 环境变量注入
注意:如果配置了 SMTP,Authelia 启动时会去连接测试,如果连不上或者密码错,容器依然会启动失败。
11.3 关闭启动检查(不推荐)
如果实在无法连通,可以设置 disable_startup_check: true。但这会导致启动时跳过检查,直到真正需要发邮件时才会暴露错误。
Authelia 新增受保护域名完整操作
一、先判断:新域名的根域是否已覆盖?
拿到新域名后,第一步不是改配置,而是判断它的根域是否已经在 session.cookies 里配置过。
| 场景 | 示例(已有 demo.com) |
需要改 session.cookies? |
|---|---|---|
| 同一根域的新子域 | newapp.demo.com |
不需要,domain: demo.com 已覆盖 |
| 全新根域 | app.demo.xyz |
需要,新增一条 cookie 配置 |
判断标准:看根域是否相同。相同 → 走流程 A;不同 → 走流程 B。
二、流程 A:同一根域下新增子域
只需改两处。
步骤 1:Caddyfile 加站点块
newapp.demo.com {
forward_auth 127.0.0.1:9091 {
uri /api/authz/forward-auth
copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
}
reverse_proxy 127.0.0.1:新应用端口
}
步骤 2:configuration.yml 的 access_control 加域名
access_control:
default_policy: 'deny'
rules:
- domain: 'wud.demo.com'
policy: 'one_factor'
- domain: 'newapp.demo.com' # 新增
policy: 'one_factor'
如果已有 *.demo.com 通配符规则,这一步可以跳过。
步骤 3:重载
sudo systemctl reload caddy
docker compose restart authelia # 仅当改了 configuration.yml 时需要
三、流程 B:全新根域
需要改四处,缺一不可。
步骤 1:configuration.yml 的 session.cookies 新增一条
session:
cookies:
- name: 'authelia_session_demo_com'
domain: 'demo.com'
authelia_url: 'https://auth.demo.com'
expiration: '1 hour'
inactivity: '5 minutes'
- name: 'authelia_session_demo_xyz' # 新增,name 必须不同
domain: 'demo.xyz'
authelia_url: 'https://auth.demo.xyz' # 必须是 demo.xyz 的子域
expiration: '1 hour'
inactivity: '5 minutes'
三个硬性要求:
name必须与已有 cookie 不同名,否则浏览器视为同一 cookie 互相覆盖。authelia_url必须是该根域的子域。写成auth.demo.com会让浏览器拒绝Domain=demo.xyz的 Set-Cookie,表现为“登录成功但一直回跳”。domain写根域,自动覆盖该根域下所有子域。
步骤 2:configuration.yml 的 access_control 加规则
access_control:
default_policy: 'deny'
rules:
- domain: '*.demo.com'
policy: 'one_factor'
- domain: '*.demo.xyz' # 新增
policy: 'one_factor'
注意:*.demo.com 的通配符不会覆盖 demo.xyz,必须单独加。
步骤 3:Caddyfile 加新的登录入口
新根域需要自己的 Authelia 入口,指向同一个容器:
auth.demo.xyz {
reverse_proxy 127.0.0.1:9091
}
以及新应用自己的站点块(同流程 A 步骤 1)。
步骤 4:重载
sudo systemctl reload caddy
docker compose restart authelia
四、操作速查表
| 改动位置 | 流程 A(同根域子域) | 流程 B(全新根域) |
|---|---|---|
session.cookies |
不动 | 新增一条(name/domain/authelia_url 都要对) |
access_control.rules |
加域名(有通配符可跳过) | 加新根域通配符 |
Caddyfile:auth.新根域 入口 |
不需要 | 需要 |
| Caddyfile:应用站点块 | 需要 | 需要 |
| 重启 Authelia | 改了 configuration.yml 才需要 | 需要 |
| 重载 Caddy | 需要 | 需要 |