服务器操作指北(15)Authentik 接入 qBittorrent 与 NPM 统一认证
创建于 2026-11-15
更新于 2026-11-15
科技
docker
qbittorrent
truenas
authentik
nginx
11886 字 · 约 40 分钟

前言

前面已经配置好 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 模式

text
1
2
3
4
5
浏览器 ──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 容器名及其网络:

bash
1
2
3
docker 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 入口验证后端认证。以下命令在能够访问该域名的终端执行:

bash
1
2
3
4
5
6
curl -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 中填写:

yaml
1
2
truenas_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 中填写:

yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
services: 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 容器检查认证端点:

bash
1
2
3
4
5
docker 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 中加入以下配置。这是本次原站点没有其他自定义内容时采用的完整片段;已有自定义规则时先合并,不直接覆盖。

nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
port_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

点击该行的齿轮,在自定义配置中填写:

nginx
1
2
3
4
5
6
7
8
auth_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 请求成功,就认为高频调用也正常。上游问题记录

参考

手机扫码阅读
本文作者: 有次元袋的 tiger
本文链接: https://www.superheaoz.top/2026/11/58244/
版权声明: 本站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 我的个人天地!