在折腾 Homelab 的过程中今天中毒了,如何保护敏感服务(如青龙面板、Portainer 等)始终是一个核心问题。直接将端口暴露在公网无异于“裸奔”,哪怕加了密码也容易被扫描和爆破。
最近我部署了 Authentik 作为统一身份认证中心,目标是:公网只开放 Authentik 的端口,所有敏感服务隐藏在后端,必须通过 Authentik 验证才能访问。
但在配置过程中,我遇到了一个经典的“网络不通”的坑。本文记录了从踩坑到完美解决的全过程,以及 Authentik 的详细配置指南。
目标是:
外网只访问一个“不常用端口”(例如
9001)青龙在
127.0.0.1:5700(宿主机回环)不对外开放通过 Authentik 原生 Proxy 去访问青龙
下面给你一套只用 Authentik 自带代理的做法(不引入额外反代软件),并且不使用 80/443。
部署步骤(Docker Compose)
你需要先知道的两个关键点
Authentik 默认端口是 9000(HTTP)/9443(HTTPS),Outpost 也在这两个端口上工作。
官方 compose 支持把“对外暴露端口”改成你想要的端口(通过
.env里的COMPOSE_PORT_HTTP/COMPOSE_PORT_HTTPS)。
1) 下载官方 compose
按官方文档下载 docker-compose.yml:
mkdir -p /opt/authentik && cd /opt/authentik
curl -O https://docs.goauthentik.io/docker-compose.yml
生成 .env 里的必需项(官方也给了 openssl 方式):
echo "PG_PASS=$(openssl rand -base64 36 | tr -d '\n')" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -d '\n')" >> .env
2) 改成“不常用端口”
在 /opt/authentik/.env 追加(示例用 9000,你可以换成别的):
COMPOSE_PORT_HTTP=9000
这样外网访问 Authentik 就会变成:
http://你的域名或IP:9000
结束之后可以使用nginx配合泛域名,将9001代理到9000实现HTTPS访问,编辑/etc/nginx/sites-available/authentik.conf
server {
# 1. 监听端口
listen 9001 ssl;
# 2. 域名 (请确保这里和 Authentik 后台填写的域名一致,是 www 还是 ql?)
server_name yanchang.cc *.yanchang.cc;
# SSL 证书配置 (路径请确认无误)
ssl_certificate /etc/nginx/ssl/www.yanchang.pem;
ssl_certificate_key /etc/nginx/ssl/www.yanchang.key;
# SSL 协议优化
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;
# Authentik 不需要太大的上传限制,但为了上传头像/图标,保留适量大小
client_max_body_size 100M;
location / {
# 指向 Authentik 的 HTTP 端口
proxy_pass http://127.0.0.1:9000;
# ========================================================
# 【关键修复】解决重定向死循环的核心
# ========================================================
# 使用 $http_host 会带上端口号 (如 :9001),而 $host 不会。
# Authentik 必须知道端口号才能生成正确的跳转链接。
proxy_set_header Host $http_host;
# ========================================================
# 【关键修复】WebSocket 支持 (Authentik 必须)
# ========================================================
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 标准代理头 (告诉 Authentik 真实 IP 和协议)
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 增加超时时间防止后台操作断开 (可选)
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
}
}sudo ln -s /etc/nginx/sites-available/authentik.conf /etc/nginx/sites-enabled/
sudo nginx -t # 检查配置有没有写错
sudo systemctl reload nginx3)启动
docker compose pull
docker compose down
docker compose up -d3) 让容器能访问宿主机的 127.0.0.1:5700解决方案:Docker 互联网络 (Bridge Network)
最干净的方案是利用 Docker 原生网络。让 Authentik 和青龙在同一个 Docker 网络中,这样 Authentik 就可以通过容器名直接访问青龙,完全不需要走宿主机 IP。
3.1 创建共享网络
Bash
docker network create authentik-internal
3.2 修改 Authentik 的 docker-compose.yml
将 Authentik 的 server 和 worker 服务加入该网络:
YAML
services:
server:
# ... 其他配置
networks:
- default
- authentik-internal
worker:
# ... 其他配置
networks:
- default
- authentik-internal
# 在文件底部声明网络
networks:
authentik-internal:
external: true
3.3 修改青龙面板的 docker-compose.yml
这是最关键的一步:
端口映射:依然只绑定
127.0.0.1,死守宿主机大门。加入网络:加入
authentik-internal,为 Authentik 开“后门”。
YAML
services:
qinglong:
image: whyour/qinglong:latest
container_name: qinglong # 【关键】记住这个容器名,它是内网的主机名
ports:
- "127.0.0.1:5700:5700" # 依然只对本机开放
networks:
- authentik-internal
# ... 其他配置
networks:
authentik-internal:
external: true
3.4 验证连通性
重启容器后,在 Authentik 容器内直接测试:
Bash
docker compose exec server sh -lc 'curl -sv --max-time 5 http://qinglong:5700/ >/dev/null'
返回 HTTP 200 或 302,说明内网已打通!
这样你在 Authentik 的 Proxy Provider 里就可以把青龙后端写成:
http://qinglong:5700
4) 启动
docker compose down
docker compose up -dAuthentik 初始配置
1) 打开初始化页面
官方初始化入口是:http://<host>:9000/if/flow/initial-setup/(注意末尾 /)
你改了端口后就是:
http://<你的域名或IP>:19000/if/flow/initial-setup/
设置 akadmin 密码后登录后台。
下面是把 Docker Compose 转化为 Systemd 服务管理的详细步骤。
第一步:清理当前运行的容器
在接管之前,我们需要先停止当前正在手动运行的容器,防止冲突。
Bash
cd /opt/authentik
docker compose down
第二步:创建 Systemd 服务文件
我们需要创建一个 .service 文件来告诉系统如何启动和停止这个服务。
创建并编辑文件:
Bash
sudo nano /etc/systemd/system/authentik.service
将以下内容复制进去(假设你的配置文件在 /opt/authentik,如果不是请修改 WorkingDirectory):
Ini, TOML
[Unit]
Description=Authentik Identity Provider
# 确保在 Docker 服务启动且网络通畅后再启动
After=docker.service network-online.target
Requires=docker.service
[Service]
Type=simple
# 设定工作目录,docker compose 会自动找这个目录下的 docker-compose.yml
WorkingDirectory=/opt/authentik
# 启动命令:使用前台模式 (up),这样 Systemd 能捕获日志
ExecStart=/usr/bin/docker compose up --remove-orphans
# 停止命令:优雅关闭所有容器
ExecStop=/usr/bin/docker compose down
# 崩溃重启策略
Restart=always
RestartSec=10
# 只有 root 才能操作,保证安全性(也可以指定其他用户,但 Docker 通常需要 root 权限或 docker 组)
User=root
Group=root
[Install]
# 开机自启的目标级别
WantedBy=multi-user.target
注意:如果你的 Docker 版本较老(使用
docker-compose命令而不是docker compose),请将ExecStart和ExecStop里的命令改为/usr/local/bin/docker-compose ...。你可以用which docker或which docker-compose检查路径。
第三步:加载并启动服务
保存文件退出后(Ctrl+O -> Enter -> Ctrl+X),执行以下命令:
重载 Systemd 配置(让系统识别新文件):
Bash
sudo systemctl daemon-reload设置开机自启:
Bash
sudo systemctl enable authentik立即启动服务:
Bash
sudo systemctl start authentik
第四步:验证状态与管理指南
现在,你可以享受到“系统级服务”的便利了。
1. 查看服务状态: 可以看到服务运行了多久,以及最新的几行日志。
Bash
sudo systemctl status authentik
2. 查看详细日志(非常方便): 这会显示 Authentik 下所有容器(Server, Worker, Redis, PG)混合在一起的实时日志,排错神器。
Bash
# 查看实时日志
sudo journalctl -u authentik -f
# 查看最近 100 行日志
sudo journalctl -u authentik -n 100
3. 重启服务: 当你修改了 docker-compose.yml 或 .env 文件后,直接重启服务即可生效:
Bash
sudo systemctl restart authentik
4. 停止服务:
Bash
sudo systemctl stop authentik
这样配置后,Authentik 就彻底变成了你系统的一部分,完全不用操心 Docker 容器的启停细节了。
一、 踩坑现场:为什么代理一直“转圈圈”?
1.1 初始配置
我最初的想法很简单:Authentik 在 Docker 容器里,青龙面板也在宿主机上跑,那我直接让 Authentik 访问宿主机的 IP 不就行了?
青龙监听:
127.0.0.1:5700(为了安全,不绑定 0.0.0.0)Authentik Proxy 配置:
Internal Host填了http://host.docker.internal:5700
1.2 故障现象
配置完成后,访问应用 URL,浏览器一直在加载中(Pending),最后超时。Authentik 似乎根本连不上后端。
1.3 排查过程
为了搞清楚发生了什么,我通过以下命令层层排查:
宿主机确认监听状态:
Bash
ss -lntp | grep 5700 # 输出:127.0.0.1:5700确实只监听了回环地址。
进入 Authentik 容器内部测试:
Bash
# 查看 host.docker.internal 解析到了哪里 docker compose exec server getent hosts host.docker.internal # 输出:172.17.0.1这里暴露了问题:
host.docker.internal解析到的是 Docker 网桥的网关 IP(172.段),而不是宿主机的127.0.0.1。容器内 Curl 测试:
Bash
docker compose exec server sh -lc 'curl -sv --max-time 5 http://host.docker.internal:5700/' # 结果:Timeout
1.4 根本原因
SSH 隧道能访问 ≠ Docker 容器能访问。
我在宿主机用 SSH 访问
127.0.0.1:5700能通,是因为我本身就在宿主机上。Docker 容器通过
172.17.0.1访问宿主机时,请求来源于“外部网络”。而青龙面板被配置为仅监听 127.0.0.1,它会拒绝来自172.17.0.1的连接请求。
最终效果与收益

完成以上配置后,当你访问 https://ql.yanchang.cc 时:
请求首先到达 Authentik。
Authentik 检查你是否登录。未登录 -> 跳转登录页。
登录成功后,Authentik 通过 Docker 内网将流量转发给
http://qinglong:5700。青龙面板的界面呈现在你面前。
这套方案的收益是非常明显的:
✅ 隐身模式:公网扫描不到青龙的端口(5700),只有 Authentik 的端口对外。
✅ 统一入口:以后再加 Portainer、Alist 等服务,都可以照葫芦画瓢,所有应用都汇聚在 Authentik 的 Portal 页面,体验类似企业的 SSO(单点登录)。
✅ 安全加固:即使青龙面板本身有漏洞,黑客也必须先突破 Authentik 的验证(支持 2FA、WebAuthn 等)才能接触到青龙。
现在,我的 Homelab 既保持了外网访问的便利性,又最大程度地确保了安全性。