前言
前面已经配置好 Authentik 的登录流程,这次接入一个实际应用:TrueNAS 上的 qBittorrent。它原本通过 Nginx Proxy Manager 提供 HTTPS,打开页面后还需要输入自己的 WebUI 密码。我希望沿用现有域名,通过 Authentik 登录后直接进入下载列表。
本文使用 qBittorrent 5.3.0、Nginx Proxy Manager(下文简称 NPM)2.14.0、TrueNAS 25.10.8,Authentik 与新增 Outpost 均为 2026.8.5。配置采用 Proxy Provider、局域网独立 Outpost 和 HTTP Basic 凭据转发,域名、地址、账号均使用示例。
Authentik 的部署见 服务器操作指北(12)Authentik 基本概念、默认配置与部署,本文复用的 DoraTiger 登录与应用授权流程见 服务器操作指北(13)Authentik DoraTiger 自建流程与默认配置清理。已绑定 Google、Microsoft 的账号也可以沿用原来的登录入口,不需要为 qBittorrent 再创建身份源。
一、接入结构与认证关系
1.1 Provider、应用与 Outpost
这次涉及的对象分布在三个管理界面中:
| 对象 | 配置位置 | 作用及关联 |
|---|---|---|
| Application 应用 | Authentik → 应用程序 | 用户看到的 qBittorrent 入口,关联 Provider,并绑定访问组 |
| Proxy Provider 代理提供者 | Authentik → 提供者 | 保存应用域名、认证模式、流程及后端 Basic 凭据属性名 |
| 访问组 | Authentik → 目录 → 组 | 指定哪些用户能进入应用,并保存本应用使用的后端凭据 |
| Proxy Outpost 前哨 | Authentik 中创建,TrueNAS 中部署 | 获取 Provider 配置,处理 NPM 发来的认证检查与登录回调 |
| Proxy Host 代理站点 | NPM | 终止 HTTPS,检查认证结果,再转发到 qBittorrent |
| WebUI 认证 | qBittorrent | 验证自己的用户名和密码,建立应用会话 |
Provider 是配置对象,Outpost 是运行组件。只创建 Provider,不部署或关联可用的 Outpost,NPM 就没有可以调用的认证服务。一个 Proxy Outpost 可以服务多个应用,但每个应用的 Provider 和访问绑定仍分别配置。
本次在 TrueNAS 部署独立 Outpost,服务账号和令牌由 Authentik 为它生成;云端继续管理用户、流程和授权。Outpost 不另建一套用户库,也不能作为云端不可达时仍能完成新登录的保证。Outpost 机制
1.2 单应用 Forward Auth
选择 Forward auth (single application),即单应用前置认证。NPM 保留现有反向代理职责,普通应用请求仍直接送到 qBittorrent;只有认证检查及 /outpost.goauthentik.io 路径进入 Outpost。每个应用可以有独立的访问规则。Forward Auth 模式
text12345浏览器 ──HTTPS──> NPM ──HTTP + Basic 凭据──> qBittorrent │ └──认证检查──> TrueNAS Proxy Outpost │ └──配置、登录授权──> 云端 Authentik
应用流量不绕行云服务器。浏览器需要能访问 Authentik 和应用域名,Outpost 也需要能访问云端 Authentik;域名解析和证书必须正常。
1.3 两层认证与账号范围
Authentik 验证用户身份,并判断这个用户是否属于允许访问的组。通过后,Outpost 生成 qBittorrent 的 Basic 认证头,由 NPM 发送给后端。浏览器不需要再填写一次 qBittorrent 密码。
这里用的是同一组 qBittorrent 管理凭据。多个 Authentik 用户获准进入后,仍操作同一个下载器,不能据此获得独立任务空间或不同的下载权限。用户名、组等身份头也不会自动把 qBittorrent 改造成多用户系统。
qBittorrent 从 5.2 开始支持 Basic Authentication,本篇实际验证的是 5.3.0。版本记录 Authentik 的 HTTP Basic 转发可以从用户或组属性中取值,本次使用专用组属性。凭据转发说明
二、部署准备
2.1 示例参数
全文使用下面这组示例,部署时统一替换:
| 参数 | 示例值 |
|---|---|
| Authentik 域名 | https://auth.example.com |
| qBittorrent 域名 | https://qb.example.com |
| TrueNAS 内网地址 | 192.0.2.10,仅用于文档示例 |
| qBittorrent WebUI 端口 | 30024 |
| NPM 已有 Docker 网络 | ix-nginx-proxy-manager_default,以本机检查结果为准 |
| Outpost 网络别名 | doratiger-authentik-outpost |
| Authentik 示例管理员 | admin-user |
qBittorrent 已经运行,NPM 也已经能把 qb.example.com 转发到 http://192.0.2.10:30024。本文只添加认证组件,不重建下载器。
操作前备份 Authentik 数据库、NPM 站点配置和 qBittorrent 配置目录。保留一个已登录的 Authentik 管理员窗口,确认知道 qBittorrent 当前用户名和密码。WebUI 配置中的密码哈希不能直接作为 Basic 密码使用。
2.2 NPM 网络与后端认证
在 TrueNAS 的 Shell 中查找 NPM 容器名及其网络:
bash123docker ps --format '{{.Names}}\t{{.Image}}' docker inspect NPM_CONTAINER_NAME \ --format '{{range $name, $config := .NetworkSettings.Networks}}{{$name}}{{println}}{{end}}'
将 NPM_CONTAINER_NAME 替换为实际容器名。记下网络名称,后面的 Outpost Compose 要加入同一个网络。网络名并不保证所有 TrueNAS 安装都一样,也不要另建一个同名但未连接 NPM 的网络。
切换前从原 HTTPS 入口验证后端认证。以下命令在能够访问该域名的终端执行:
bash123456curl -s -o /dev/null -w '%{http_code}\n' \ https://qb.example.com/api/v2/app/version # 只填写用户名,curl 会交互式询问密码,避免密码进入命令历史 curl --user QBIT_USERNAME \ https://qb.example.com/api/v2/app/version
本次匿名请求返回 403,Basic 请求返回 v5.3.0。这说明原入口确实需要认证,不能只看到配置中有网段白名单,就判断当前访问者一定免密码。
三、访问组与后端凭据
同一种服务可能部署在不同位置,因此应用 Slug、Provider、访问组和凭据属性都包含部署位置。本文使用 truenas-qbittorrent;如果另有 PVE 实例,则使用 pve-qbittorrent 及其独立凭据。Outpost 按所在位置命名为 doratiger-truenas-proxy,可以关联该位置的多个应用,不必为每个应用重复部署。
3.1 创建应用访问组
进入 Authentik 管理员界面,“目录 → 组 → 创建”,Name 填 truenas-qbittorrent-admins。它只管理这个下载器的访问范围,不要启用组的超级用户权限。
保存后打开组详情,在用户成员页面加入需要访问 qBittorrent 的现有账号,例如 admin-user。如果从用户详情操作,则编辑该用户的组成员关系,选中刚创建的组并保存。仅创建组名称还不够,用户必须实际成为成员。
3.2 配置组属性
编辑 truenas-qbittorrent-admins,在 Attributes 中填写:
yaml12truenas_qbittorrent_username: 'REPLACE_WITH_QBIT_USERNAME' truenas_qbittorrent_password: 'REPLACE_WITH_QBIT_PASSWORD'
两项都替换为 qBittorrent 的实际凭据,不是 Authentik 管理员密码。密码中含单引号时,按 YAML 规则用两个单引号转义,保存前确认编辑器没有语法错误。
属性键稍后要填进 Provider。truenas_qbittorrent_username 是键名,键的值才是后端账号;不能把用户名直接填到 Provider 的 Username Key 中。
这两个属性是可读取的后端凭据,应限制组属性的查看、修改和导出权限。不要写进公开蓝图、博客截图、Git 仓库或 NPM 配置。用户可编辑的个人属性也不应允许随意覆盖这些敏感键。这里只分配受信任的管理员使用下载器。
四、Proxy Provider 与应用
4.1 创建代理提供者
进入“应用程序 → 提供者 → 创建”,类型选 Proxy Provider。填写:
| 字段 | 配置值及用途 |
|---|---|
| Name | doratiger-truenas-qbittorrent,用于后台识别 |
| Authentication flow | doratiger-authentication,复用已有登录流程 |
| Authorization flow | doratiger-provider-authorization-implicit-consent,通过访问检查后免弹出同意页 |
| Invalidation flow | doratiger-provider-invalidation,复用提供者退出流程 |
| Mode | Forward auth (single application) |
| External host | https://qb.example.com,填写应用地址 |
| Cookie domain | 保留默认,不扩大到整个父域 |
| Unauthenticated paths | 留空,应用 API 也需要认证 |
选择 Forward Auth 后,qBittorrent 后端地址由 NPM 管理,不在此处设置 Proxy 模式的 Internal host。External host 必须与浏览器实际使用的域名一致,不能填 auth.example.com 或 Outpost 容器名。
在 HTTP Basic 相关设置中继续填写:
| 字段 | 配置 |
|---|---|
| Send / Set HTTP-Basic Authentication | 开启 |
| HTTP-Basic Username Key | truenas_qbittorrent_username |
| HTTP-Basic Password Key | truenas_qbittorrent_password |
| Intercept header authentication | 本次关闭;浏览器入口使用现有登录会话 |
发送后端 Basic 凭据和接收客户端 Basic 登录是两个方向,不要混为一谈。此处的目标是让 Outpost 给 qBittorrent 提供凭据。关闭 Intercept 也不意味着跳过应用访问检查。HTTP 头认证
保存 Provider。若使用的仍是默认流程,须选择自己已验证可用的对应流程;不要仅照抄不存在的 doratiger- 名称。
4.2 创建应用并关联 Provider
进入“应用程序 → 应用程序”,创建时选择 with existing provider,使用刚创建的提供者:
| 字段 | 填写内容 |
|---|---|
| Name | TrueNAS · qBittorrent |
| Slug | truenas-qbittorrent |
| Provider | doratiger-truenas-qbittorrent |
| Launch URL | https://qb.example.com |
保存后打开应用详情,确认 Provider 已关联。Name 是用户在应用列表看到的名字,Slug 是 Authentik 内部标识,Launch URL 才是点击应用时打开的地址。
4.3 绑定访问组
在该应用的“策略/组/用户绑定”中创建绑定,选择组 truenas-qbittorrent-admins,Order 填 0,启用绑定,Negate 保持关闭,然后保存。
这里直接使用组绑定,不需要再写一条“判断是否属于组”的 Expression Policy。免确认授权流程只是不弹出同意页,应用的组限制仍需检查。组里保存凭据也不会自动限制应用访问,组成员、应用绑定和 Provider 属性引用三项都要完成。
验证时使用一个组成员和一个非成员账号。成员应能访问,非成员应被拒绝;只看到应用卡片不能代替实际访问测试。
五、TrueNAS Proxy Outpost
5.1 在 Authentik 创建 Outpost
进入“应用程序 → 前哨(Outposts)→ 创建”:
| 字段 | 配置 |
|---|---|
| Name | doratiger-truenas-proxy |
| Type | Proxy |
| Integration / 服务连接 | 留空,选择手动部署 |
| Applications | 选中刚创建的 TrueNAS · qBittorrent |
在高级配置中把 authentik_host 设置为 https://auth.example.com/,证书校验保持开启,其他设置保留默认。保存后,在该 Outpost 的部署信息中查看手动部署所需的 Token。这里使用系统为此 Outpost 生成的受限令牌,不创建全局管理员 API Token。
Outpost 选择应用,实际使用的是应用关联的 Provider。创建记录后还没有运行容器,需要继续部署。不要选择云端 Docker Integration,否则它可能在云服务器而不是 TrueNAS 上创建容器。
5.2 创建 TrueNAS 自定义应用
在 TrueNAS 的“Apps → Discover Apps”进入 Install via YAML,应用名称填 authentik-outpost。不同界面布局中,该入口可能位于更多操作菜单内。TrueNAS 自定义应用
在 Custom Config 中填写:
yaml1234567891011121314151617services: proxy: image: ghcr.io/goauthentik/proxy:2026.8.5 restart: unless-stopped environment: AUTHENTIK_HOST: https://auth.example.com/ AUTHENTIK_INSECURE: 'false' AUTHENTIK_TOKEN: 'REPLACE_WITH_OUTPOST_TOKEN' networks: npm: aliases: - doratiger-authentik-outpost networks: npm: external: true name: ix-nginx-proxy-manager_default
替换域名、Token 和已核对的 NPM 网络名称,然后保存。示例镜像与本次云端 server、worker 版本一致;手动部署的 Outpost 需要随服务端维护版本。官方 Compose 部署说明
这里没有 ports:NPM 通过共享 Docker 网络访问 Outpost 的容器端口 9000,不用先映射宿主端口。npm 是当前 Compose 文件内的网络键,name 才是宿主机上已有网络的名字,doratiger-authentik-outpost 则是 NPM 可以解析的别名。
Token 将保存在 TrueNAS 应用配置中,应限制管理权限并保护配置备份。本例无需挂载 Docker socket,也不在 TrueNAS 再部署 Authentik 数据库。
5.3 验证 Outpost
等待 TrueNAS 安装任务成功、应用进入运行状态,再到 Authentik Outpost 页面检查连接状态。只有容器启动、没有连上云端,仍不能切换 NPM。
在 TrueNAS Shell 中,从 NPM 容器检查认证端点:
bash12345docker exec NPM_CONTAINER_NAME curl -s -o /dev/null \ -w '%{http_code}\n' \ -H 'Host: qb.example.com' \ -H 'X-Original-URL: https://qb.example.com/' \ http://doratiger-authentik-outpost:9000/outpost.goauthentik.io/auth/nginx
本次无会话请求返回 401,说明已到达认证检查接口。若名称解析失败,检查是否在同一个 Docker 网络;连接失败则检查容器、端口和 Outpost 状态。不要把 401 当作安装失败去关闭认证。
六、NPM 认证配置
6.1 原代理站点
进入 NPM 的“Hosts → Proxy Hosts”,编辑现有 qb.example.com 站点。Details 中仍保留:
| 字段 | 示例 |
|---|---|
| Domain Names | qb.example.com |
| Scheme | http |
| Forward Hostname / IP | 192.0.2.10 |
| Forward Port | 30024 |
SSL 页继续使用原证书和 Force SSL。这里不把转发目标改为 Outpost;普通页面和 API 仍由 qBittorrent 响应。
NPM 没有新增的 Authentik 开关。本次修改在同一站点的 Advanced 和 Custom Locations 两处,按官方 NPM 配置方式分别填写。
6.2 Advanced:Outpost 路由与登录跳转
在 Advanced 中加入以下配置。这是本次原站点没有其他自定义内容时采用的完整片段;已有自定义规则时先合并,不直接覆盖。
nginx123456789101112131415161718port_in_redirect off; set $ak_http_host $host; location /outpost.goauthentik.io { proxy_pass http://doratiger-authentik-outpost:9000; proxy_set_header Host $ak_http_host; proxy_set_header X-Original-URL $scheme://$ak_http_host$request_uri; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass_request_body off; proxy_set_header Content-Length ""; } location @goauthentik_proxy_signin { internal; add_header Set-Cookie $auth_cookie; return 302 /outpost.goauthentik.io/start?rd=$scheme://$ak_http_host$request_uri; }
第一段把应用域名下的 Outpost 路径送到局域网容器,包含认证检查、登录开始和回调。它不能再被自己的 auth_request 保护,否则登录入口本身也会要求先登录。
Host 和 X-Original-URL 告诉 Outpost 当前访问的是哪个应用及哪个地址。这里使用标准 HTTPS 443;若应用对外使用非标准端口,应按官方模板保留完整 Host,包括端口,不能照搬本例的 $host。
第二段是 Nginx 内部命名 location,用于接收未登录结果并跳转。rd 保存登录后返回的应用地址。
6.3 Custom Locations:保护应用与转发凭据
切换到 Custom Locations,新增或编辑 /:
| 字段 | 示例 |
|---|---|
| Location | / |
| Scheme | http |
| Forward Hostname / IP | 192.0.2.10 |
| Forward Port | 30024 |
点击该行的齿轮,在自定义配置中填写:
nginx12345678auth_request /outpost.goauthentik.io/auth/nginx; error_page 401 = @goauthentik_proxy_signin; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; auth_request_set $authentik_auth $upstream_http_authorization; proxy_set_header Authorization $authentik_auth;
这里不要再套 location / {},也不写 proxy_pass,NPM 会根据表单生成它们。Advanced 与 Custom Locations 填写完成后一起保存,确认站点仍为 Online。若保存失败,先恢复备份,查看具体语法错误。
六行配置分别负责:
| 配置 | 作用 |
|---|---|
auth_request |
在访问后端前调用 Outpost |
error_page 401 |
未登录时进入前面的内部跳转路由 |
auth_request_set $auth_cookie |
读取认证子请求返回的 Cookie |
add_header Set-Cookie |
把需要更新的认证 Cookie 交给浏览器 |
auth_request_set $authentik_auth |
读取 Outpost 返回的后端 Basic 认证头 |
proxy_set_header Authorization |
用该认证头访问 qBittorrent |
$upstream_http_authorization 来自认证子请求的响应,不是直接信任浏览器提供的头。这里只传递后端需要的凭据,没有额外发送它不会使用的用户姓名和组列表。
如果站点还有其他自定义 location 直接代理 qBittorrent,也要覆盖相同认证检查。不要为 /api/ 添加匿名例外。已有 NPM IP Access List 时,还应检查自定义 location 的继承设置,并验证认证通过也不能绕过 IP 限制。
6.4 保存与持久化
保存后重新打开站点编辑窗口,应能在上述两个位置看到配置。NPM 根据保存的数据生成 Nginx 文件;只在容器里编辑生成文件,后续保存站点时可能被覆盖。
本次通过 NPM 原生数据模型保存并调用其配置生成方法,最后完成语法检查和重载。按本文从 WebUI 操作会落在相同的配置位置,无需手工修改 SQLite 数据库。
七、qBittorrent 后端认证
7.1 关闭免认证例外
先用无痕窗口完成 Authentik 登录,确认直接进入下载列表,再调整后端认证。不要把免认证当作消除第二次密码提示的办法;本次由 Basic 转发解决该问题。
在 qBittorrent 的“工具 → 选项 → Web UI”中找到认证设置,取消:
- Bypass authentication for clients on localhost:本机客户端免认证。
- Bypass authentication for clients in whitelisted IP subnets:白名单网段免认证。
保存后,原白名单文本即使仍在,也不再因该开关获得免认证。对应 API 偏好键为 bypass_local_auth 和 bypass_auth_subnet_whitelist_enabled,本次均设置为 false。
这里没有更改 qBittorrent 用户名、密码或下载目录。5.3 的配置文件已使用独立 [WebUI] 段,排查时不能只搜索旧版的 WebUI\... 键。运行时修改优先使用界面或原生 API,避免手改文件后被进程写回覆盖。
7.2 其他安全设置
统一认证保护的是 NPM 上的 HTTPS 入口。直接通过 IP 和端口访问后端仍使用 qBittorrent 自身认证,不会自动经过 Authentik。
本次没有同时修改 CSRF、Host Header 校验和可信代理范围,原实例在这些方面仍有需要收紧的配置。应在统一登录稳定后逐项核对 Host、Origin、Referer 和可信代理来源,再恢复对应校验;不能把关闭这些保护当作统一认证的必要条件。
Basic 凭据本身不是加密数据,当前 NPM 到后端的 HTTP 连接仅位于受控本机网络。若把后端放到另一台不可信网络中的主机,应另行保护这段传输。
八、验证与维护
8.1 验证结果
| 检查项 | 本次结果 |
|---|---|
| TrueNAS Outpost | 应用安装成功,容器 healthy |
| NPM 配置 | 语法校验与重载成功 |
| HTTPS 匿名访问主页、版本 API、任务 API | 均返回 302,最终到达 DoraTiger 登录流程 |
| 应用访问组 | 策略检查中,成员允许、非成员拒绝 |
| 浏览器实际登录 | 完成 Authentik 登录后直接进入下载列表,不再输入后端密码 |
| qBittorrent 内部匿名 API | 关闭免认证后返回 403 |
| 后端 Basic 认证 | 正常返回 5.3.0 版本 |
| 统一退出 | 尚未单独完成跨层会话验证 |
Authentik 登录会话、Outpost 会话和 qBittorrent 会话各有生命周期,不能把“登录成功”直接写成“单点退出也成功”。退出按钮的行为需要单独验证。
8.2 凭据与版本维护
修改 qBittorrent 密码后,同步更新 Authentik 组属性。Authentik 的 Basic 属性在用户向代理认证时读取,已有会话可能仍使用旧值,更新后要重新认证验证。
手动部署的 Outpost 不依赖云端 Docker Integration 自动升级。维护 Authentik 时,一并检查 server、worker、Outpost 的版本及连接状态。NPM 网络改名或重建后,也要核对 Outpost 的外部网络引用。
8.3 回退
优先恢复 NPM 原站点的 Advanced 和 Custom Locations,使 HTTPS 入口重新直接到达 qBittorrent。保留后端密码认证即可,无须重新开启网段免认证。
NPM 不再调用 Outpost 后,才停止 TrueNAS 上的新增应用。需要删除 Authentik 对象时,按应用、Provider、Outpost、组的实际引用处理;不要为了撤销少量对象恢复整个身份数据库,覆盖期间的其他修改。
九、配置问题与解答
9.1 TrueNAS 显示 5.0.4 已是最新版
Q:是不是社区 App 没有继续维护?
本次并不是。检查时,官方目录已有 5.3.0,但本机 catalog.sync 曾因拉取 GitHub 仓库失败而报错。原生目录同步重试成功后,应用从“无更新”变为可更新到 5.3.0 / 1.4.21。刷新目录和升级应用是两项操作,目录恢复并没有自动升级下载器;确认更新后才进行升级。TrueNAS 应用目录
9.2 NPM 没有新的认证配置项
Q:已经接入成功,为什么 Details 页面看不到 Authentik?
NPM 没有专用开关。配置保存在原 Proxy Host 的 Advanced,以及 Custom Locations 中 / 旁边的齿轮内。刷新页面、重新进入站点编辑窗口即可检查,不需要寻找一个新建的代理站点。
9.3 通过 Authentik 后仍要求输入 qBittorrent 密码
Q:登录页跳转成功,为什么还要登录一次?
前置身份检查和后端凭据转发是两步。检查 Provider 是否开启 Basic 转发、组属性键是否拼写一致、用户是否属于该组,以及 NPM 是否配置了读取和转发 Authorization 的两行。再单独验证这组凭据能否登录 qBittorrent;不要先扩大免认证网段。
9.4 配置有白名单,实际仍需要密码
Q:配置文件启用了网段免认证,为什么浏览器仍出现登录框?
经过反代后,实际连接来源、转发头和可信代理判断都会影响请求身份。本次切换前的 HTTPS 匿名 API 明确返回 403,Basic 才返回 200。配置文本只能作为排查线索,最终应按实际访问路径测试。
9.5 Nginx 重载提示 Operation not permitted
Q:容器内已经是 root,为什么不能重载?
本次通过命令调用 NPM 配置生成时遇到了这个问题:Nginx 主进程 UID 是 1000,容器 root 又没有向其他 UID 进程发信号所需的 capability。改用该实例的 Nginx 运行用户执行重载后成功,没有额外增加权限。不同镜像和应用配置的 UID 可能不同,不能把 1000 当作统一默认值。正常从 NPM WebUI 保存时无需额外执行这一步。
9.6 Basic 请求反复创建会话
Q:能登录,但为什么会话不断增加?
5.3.0 有上游问题记录:有效 Basic 请求如果不带可用的会话 Cookie,可能每次创建新会话。浏览器代理应正确保留后端 Cookie。不要只验证一个无 Cookie 的 curl 请求成功,就认为高频调用也正常。上游问题记录
参考
支付宝
微信