前言
qBittorrent 接入后,这次继续处理 TrueNAS 上的 Gitea。Gitea 已经有正在使用的账号和仓库,我希望保留它们,通过 DoraTiger Auth 登录;以后有内部人员加入,也能在首次登录时自动创建自己的账号,再自行建立仓库。
这里遇到的第一个问题是两边账号资料不一致:Gitea 的用户名和邮箱,与 Authentik 中的账号不同。接入时需要先完成原账号关联,再开放新用户自动注册,避免把原来的用户当成新用户创建一遍。
本文使用 Gitea 28.3.0、TrueNAS 25.10.8 和 Authentik 2026.8.5。Gitea 已通过 Nginx Proxy Manager(NPM)提供 HTTPS,本文保留原反代,使用原生 OpenID Connect(OIDC)认证。域名、账号和部署路径均使用示例。
Authentik 的部署见 服务器操作指北(12)Authentik 基本概念、默认配置与部署,下文复用的登录、应用授权和退出流程见 服务器操作指北(13)Authentik DoraTiger 自建流程与默认配置清理。本文不重新部署 Gitea,也不迁移已有仓库和组织。
一、OIDC 与账号关系
1.1 认证结构
Gitea 自带 OIDC 客户端。点击登录按钮后,由 Gitea 发起授权请求,Authentik 完成用户认证,再把结果交回 Gitea。它不需要上一例中的 Proxy Provider、Outpost 或 NPM auth_request。Authentik Gitea 接入文档
text1234567891011浏览器 → Gitea 登录页 → DoraTiger Auth ↓ Authentik 登录、MFA 与应用访问检查 ↓ 浏览器 ← Gitea 回调地址 ← 授权码 ↓ Gitea 服务端向 Authentik 换取令牌、验证身份 ↓ 查找已有绑定,或按注册设置创建 Gitea 用户 ↓ 建立 Gitea 登录会话
浏览器必须能访问两个 HTTPS 域名,Gitea 容器也必须能访问 Authentik 的发现文档、令牌等端点。浏览器能打开 Authentik,并不能证明 Gitea 后端也能连通。
NPM 继续负责原来的 HTTPS 转发。Gitea 的 ROOT_URL 应与浏览器实际使用的地址一致,例如 https://git.example.com/。不要为了接入 OIDC,再给这个站点叠加一套 Forward Auth。
1.2 前哨与原生 OIDC
服务器操作指北(15)Authentik 接入 qBittorrent 与 NPM 统一认证 中部署了 TrueNAS Proxy Outpost,但这个前哨并不是局域网内所有应用的统一认证中转站。是否使用它,取决于应用采用的认证协议和接入方式,而不是应用是否部署在 TrueNAS 上。前一篇的 qBittorrent WebUI 没有使用原生 OIDC 登录,仍然验证自己的用户名和密码。因此,这套方案由 NPM 在转发请求前调用 Proxy Outpost,检查用户是否已经通过 Authentik 认证、是否允许访问应用;通过后,再把 Outpost 提供的 HTTP Basic 凭据转发给 qBittorrent。前哨承担了应用入口的认证检查和后端凭据转发所需的处理,qBittorrent 自身不负责解析 Authentik 的 OIDC 身份。
Gitea 则具备原生 OIDC 客户端,可以自己发起授权、处理回调、换取令牌,并将外部身份关联到自己的用户。它直接连接云端 Authentik 的 OAuth2/OpenID Connect Provider,因此不需要通过 TrueNAS 上的 Proxy Outpost。
| 对比项 | 本次 qBittorrent 接入 | 本次 Gitea 接入 |
|---|---|---|
| Authentik 提供者 | Proxy Provider | OAuth2/OpenID Connect Provider |
| 谁处理应用侧的统一认证 | NPM 调用 TrueNAS Proxy Outpost | Gitea 自带的 OIDC 客户端 |
| NPM 的工作 | HTTPS 反代、认证子请求、转发后端 Basic 凭据 | 保留原 HTTPS 反代 |
| 应用接受的登录凭据 | qBittorrent 自身的用户名和密码 | Authentik 提供的 OIDC 身份,关联到 Gitea 用户 |
| TrueNAS 前哨 | 使用 | 不使用 |
| 云端 Authentik | 负责用户登录、MFA 和授权 | 负责用户登录、MFA、授权及令牌签发 |
这里的“直接连接云端”指认证协议的交互:浏览器跳转到云端登录,Gitea 服务端也向云端请求发现文档和令牌。用户访问 Gitea 页面仍经过原来的 NPM,业务流量不需要先绕到云端 Authentik。
前哨也不是独立身份中心。前一篇把它部署在 TrueNAS,是为了让 NPM 在本地网络中调用认证端点,并没有为局域网复制一套能够独立完成新登录的用户库。两种方案都不能仅凭“组件部署在本地”就认定云端不可达时仍可完成新认证;已有应用会话是否继续有效,则取决于各自的会话状态。
1.3 身份源、Provider 与本地用户
| 对象 | 本次用途 |
|---|---|
| Authentik Source 身份源 | Google、Microsoft 等上游登录方式,已经配置的可继续使用 |
| Authentik OAuth2/OpenID Connect Provider | 向 Gitea 提供用户身份和令牌 |
| Authentik Application 应用 | 关联 Provider、设置入口并绑定访问条件 |
| Gitea 认证源 | 保存 OIDC 客户端参数,显示 DoraTiger Auth 登录入口 |
| Gitea 用户 | 保存仓库归属、组织成员关系、权限、SSH Key 等应用数据 |
Google 和 Microsoft 登录的是 Authentik 账号。Gitea 只接收 Authentik 提供的身份,无须再分别接入这两个上游。Source 与 Provider 的方向不同:前者让 Authentik 接受外部身份,后者让其他应用接受 Authentik 的身份。OAuth2 Provider 说明
统一登录后,Gitea 仍然需要自己的用户记录。已有用户关联身份后继续使用原记录;新用户首次登录时自动建立记录,也属于创建 Gitea 账号,只是省去了另一份注册表单。
1.4 命名与示例地址
同一种服务以后可能部署在多个位置,因此后台对象保留部署位置,登录按钮则使用品牌名称:
| 字段或对象 | 示例值 |
|---|---|
| Authentik 域名 | https://auth.example.com |
| Gitea 对外地址 | https://git.example.com/ |
| 应用名称 | TrueNAS · Gitea |
| 应用 Slug | truenas-gitea |
| Provider 名称 | doratiger-truenas-gitea |
| Authentik 访问组 | truenas-gitea-users |
| Gitea 认证源名称 | DoraTiger Auth |
应用 Slug 会进入发现文档地址,Gitea 认证源名称会进入回调路径。两个字段不能互换,也不能只改显示名称而忽略它对应的 URL。
二、Authentik 应用配置
2.1 访问组
进入 Authentik 管理员界面的“目录 → 组”,创建 truenas-gitea-users 并保存。打开组的用户列表,将准备关联 Gitea 的管理员账号加入。
这个组只表示允许使用此 Gitea 的 OIDC 入口。它不等于 Gitea 管理员组,也不会自动创建 Gitea 组织、团队或分配仓库权限。本次先只加入已有管理员对应的 Authentik 用户。
2.2 OAuth2/OpenID Connect Provider
在“应用程序 → 提供者”中新建提供者,类型选择 OAuth2/OpenID Connect。以下名称来自前文已经创建的流程;如果使用自己的命名,应选择用途对应的对象。
| 字段 | 本次选择及作用 |
|---|---|
| Name | doratiger-truenas-gitea,标识这个 Gitea 实例的提供者 |
| Authentication flow | doratiger-authentication,执行已有登录与 MFA |
| Authorization flow | doratiger-provider-authorization-implicit-consent,应用授权时不增加逐次确认页面 |
| Invalidation flow | doratiger-provider-invalidation,复用 Provider 退出流程 |
| Client type | Confidential,Gitea 服务端保管客户端密钥 |
| Client ID、Client Secret | 保留生成值,稍后填写到 Gitea;密钥不放入公开配置 |
| Grant types | 启用 Authorization code,对应 authorization_code |
| Signing key | 选择现有签名证书,用于令牌签名 |
| Subject mode | 本次保留 hashed_user_id,不要在关联完成后随意更换 |
名称中带 implicit-consent 的是“免确认授权流程”,不代表 OAuth 的 Implicit grant。这里实际使用的仍然是授权码模式。
在 Redirect URIs 中新增一条:
| 字段 | 值 |
|---|---|
| 匹配方式 | Strict |
| URI 类型 | Authorization |
| URI | https://git.example.com/user/oauth2/DoraTiger%20Auth/callback |
认证源名称中的空格在路径中编码为 %20。大小写、域名、路径及末尾斜杠都应与 Gitea 实际发送的 redirect_uri 一致;不要用扩大匹配范围来掩盖地址错误。本次没有额外配置 Post Logout 回调。
在 Scope mappings 中选择提供 openid、email、profile 的标准映射,分别用于 OIDC 身份、邮箱及基本资料。本次没有添加组织团队或管理员权限映射。保存 Provider,并记录客户端参数。
sub 是 OIDC 中标识用户的 Subject。账号关联后,应保留原用户和 Provider 的身份配置;修改用户名、邮箱与改变 Subject 的含义不同,不能把邮箱当作稳定身份绑定的替代品。
2.3 应用与组绑定
进入“应用程序 → 应用程序”,新建应用。如果界面先让选择创建方式,使用 with existing provider,关联刚才的 Provider。
| 字段 | 填写内容 |
|---|---|
| Name | TrueNAS · Gitea |
| Slug | truenas-gitea |
| Provider | doratiger-truenas-gitea |
| Launch URL | https://git.example.com/ |
保存后打开该应用的策略/组/用户绑定页面,创建组绑定:选择 truenas-gitea-users,保持启用,不取反,顺序设为 0。本例只有这一条访问绑定,不额外添加一个允许所有人的绑定。
绑定位置是 Application。只创建组但不绑定,不能限制应用访问;把名称填进应用的展示分组字段,也不等于授权。
2.4 发现文档
应用保存后,对应发现文档为:
text1https://auth.example.com/application/o/truenas-gitea/.well-known/openid-configuration
它使用应用 Slug,不使用 Provider 名称。可以从 Gitea 容器测试连通性;以下命令在 TrueNAS Shell 执行,容器名替换为本机实际值,且要求容器内有 curl:
bash12docker exec GITEA_CONTAINER_NAME curl -fsS \ https://auth.example.com/application/o/truenas-gitea/.well-known/openid-configuration
应返回包含 issuer、授权端点、令牌端点和公钥地址的 JSON。请求失败时先处理 DNS、证书信任或网络访问,不通过跳过 TLS 校验来完成接入。
三、Gitea 认证源
3.1 新建认证源
先使用 Gitea 原有管理员账号登录,进入“站点管理 → 认证源”,新建认证源。不同语言版本可能显示为 Authentication Sources,按字段核对:
| 字段 | 本次填写 |
|---|---|
| Authentication type | OAuth2 |
| Authentication name | DoraTiger Auth |
| OAuth2 provider | OpenID Connect |
| Client ID / Key | Authentik Provider 中的 Client ID |
| Client Secret | 同一 Provider 中的 Client Secret |
| OpenID Connect Auto Discovery URL | 上一节的发现文档完整地址 |
| Additional scopes | email、profile,按界面分别添加;openid 由 OIDC 客户端处理 |
| 启用认证源 | 开启 |
管理员组、组织团队和受限用户映射本次不填写。Authentik 管理员身份不会因此自动变成 Gitea 管理员。Gitea 认证说明
本次实际通过 Gitea 原生 CLI 创建认证源,表中给出对应的 WebUI 配置方式。保存后,退出或使用无痕窗口检查登录页,应出现 DoraTiger Auth 按钮。此时先保持自动注册关闭,完成已有账号关联。
3.2 配置保存位置
认证源的客户端参数保存在 Gitea 的数据库中;后面的注册开关保存在 app.ini。两者都需要纳入备份。
修改前备份 Gitea 配置和数据库,并确认仓库、附件、LFS 等已有数据的备份可用。不要为了新增认证源重新初始化应用,也不要覆盖 TrueNAS 已有存储挂载。
四、已有账号关联
4.1 用户名与邮箱不同
假设 Gitea 原账号为 codeowner,Authentik 账号为 identityadmin,两边邮箱也不同。无需先把邮箱改成一致,应该分别验证两侧账号,再建立关联。
- 使用原密码登录 Gitea 的
codeowner。 - 打开“用户设置 → 安全 → 管理关联账号”,也可以访问
https://git.example.com/user/settings/security。 - 在关联入口选择
DoraTiger Auth。 - 跳转到 Authentik 后,确认当前使用的是准备绑定的
identityadmin,完成登录和 MFA。 - 返回 Gitea 后,重新打开安全设置,确认关联列表出现 DoraTiger Auth,并且当前用户仍是
codeowner。 - 退出 Gitea,在无痕窗口通过 DoraTiger Auth 登录,检查原仓库和组织权限是否仍然存在。
Authentik 如果已经有会话,可能直接完成授权。不要因为没有再次输入密码,就忽略了当前会话究竟属于哪个用户。
本次先保持自动注册关闭,再完成原账号关联,最终确认仍使用原 Gitea 用户。这里没有修改原邮箱、迁移仓库或重新授予管理员权限。
4.2 同名账号与自动合并
后面配置中的 ACCOUNT_LINKING=login 表示发生已有账号冲突时,要求登录原账号完成关联。不要改成 auto 来省略这次确认;两个系统提供相同邮箱或用户名,不应直接作为接管已有仓库的依据。
手动关联成功后,Gitea 通过保存的外部身份关联查找原用户。已有用户关联与新用户自动注册是两条路径,不要求每个用户都重新注册一遍。
五、新用户自动注册
5.1 app.ini 与持久化
原账号关联成功后,再修改 Gitea 配置。本次是 TrueNAS 中运行的 rootless Gitea,容器内配置位于 /etc/gitea/app.ini;宿主机路径由应用存储挂载决定。不要把另一个镜像的 /data/gitea/conf/app.ini 直接套用到本实例。
在 TrueNAS 的应用存储配置中找到映射到 /etc/gitea 的持久目录。下文统一以宿主机 /srv/example/gitea/config/app.ini 举例,实际操作前替换路径。先备份:
bash123cp -p /srv/example/gitea/config/app.ini \ /srv/example/gitea/config/app.ini.before-oidc-registration chmod 600 /srv/example/gitea/config/app.ini.before-oidc-registration
如果 TrueNAS 应用设置中同时配置了相应 GITEA__... 环境变量,应从部署入口统一修改,避免启动时重新覆盖。以下是需要合并到现有文件的配置片段,不是完整 app.ini;已有同名节和键直接修改,不重复追加,也不覆盖数据库和加密密钥。
ini1234567891011121314[oauth2_client] ENABLE_AUTO_REGISTRATION = true ACCOUNT_LINKING = login USERNAME = nickname [service] DISABLE_REGISTRATION = false ALLOW_ONLY_EXTERNAL_REGISTRATION = true ALLOW_ONLY_INTERNAL_REGISTRATION = false REQUIRE_EXTERNAL_REGISTRATION_PASSWORD = false DEFAULT_ALLOW_CREATE_ORGANIZATION = false [repository] DEFAULT_PRIVATE = private
5.2 注册开关
| 配置 | 本次作用 |
|---|---|
ENABLE_AUTO_REGISTRATION=true |
外部身份没有对应 Gitea 用户时,允许自动建号 |
DISABLE_REGISTRATION=false |
打开注册总开关,否则自动建号也受限制 |
ALLOW_ONLY_EXTERNAL_REGISTRATION=true |
保留外部认证注册,关闭本地密码注册入口 |
ALLOW_ONLY_INTERNAL_REGISTRATION=false |
不将注册限制为内部账号 |
REQUIRE_EXTERNAL_REGISTRATION_PASSWORD=false |
外部注册不额外要求设置 Gitea 密码 |
USERNAME=nickname |
按身份源提供的昵称资料生成新用户名 |
ACCOUNT_LINKING=login |
已有账号冲突交由原账号登录确认 |
因此,DISABLE_REGISTRATION=false 在这里不等于开放匿名本地注册,它和“仅外部注册”一起工作。本地管理员密码登录与本地注册也是不同功能,关闭后者不会自动关闭前者。Gitea 配置说明
新用户资料需要能满足 Gitea 的用户名、邮箱等要求,冲突或资料不完整时仍可能需要处理。原实例的邮箱注册确认关闭,本次没有另开 Gitea 邮箱确认;如果另一实例启用了邮件确认或人工审核,也要检查 [service] 和 [oauth2_client] 中的相关设置。
5.3 仓库与组织权限
DEFAULT_PRIVATE=private 只让新建仓库默认选择私有,不禁止用户主动创建公开仓库,也不修改原仓库可见性。
DEFAULT_ALLOW_CREATE_ORGANIZATION=false 控制新用户默认的组织创建权限。已有组织与已有用户权限不随这一开关批量改变。当前只需要每个人管理自己的仓库,因此没有增加组织、团队或仓库配额;已有实例若另有限制,应检查其仓库创建上限和用户状态。
网页 OIDC 登录也不会替代 Git 客户端的认证。SSH 继续使用用户在 Gitea 中登记的 SSH Key;HTTPS Git 操作按 Gitea 的令牌等方式配置,不把 Authentik 密码或 Client Secret 当作 Git 密码。
5.4 重启与检查
修改持久文件后,在 TrueNAS 中重启 Gitea 应用,或在确认容器归属后只重启 Gitea 服务容器:
bash1docker restart GITEA_CONTAINER_NAME
无需为这些开关重启数据库。重新打开登录与注册页面,确认品牌登录按钮仍在、本地管理员登录仍可用,注册页不再显示本地密码注册表单。然后从容器实际使用的配置位置核对上述键,确认未被环境变量覆盖。
六、访问组与用户生命周期
6.1 新用户开通
管理员在 Authentik 邀请或创建用户后,将其加入 truenas-gitea-users。用户在 Gitea 点击 DoraTiger Auth,完成 Authentik 登录;应用绑定允许访问后,Gitea 才能继续处理回调并按配置建号。
这里有两道不同的判断:Authentik 访问组决定是否允许进行这次应用认证;Gitea 注册配置决定收到一个新身份后是否创建本地用户。只打开自动注册,不把用户加入访问组,仍不能通过这个入口登录。
用户建立 Gitea 账号后,默认管理自己的个人仓库。需要参与公共工作时,再由 Gitea 管理员添加组织成员或团队权限。本次没有把 Authentik 的所有组同步成 Gitea 组织。
6.2 撤销访问
从 Authentik 组中移除用户,可限制其后续通过该应用发起的认证,但不等于立即注销所有已有 Gitea 会话,也不会自动删除 Gitea 用户、SSH Key、个人访问令牌或仓库。
人员离开时,还需要在 Gitea 侧处理账号状态、有效凭据和仓库交接。不能只从访问组删除用户,就认定 SSH、API 和所有已登录会话都同时失效。本次也没有配置完整的跨应用单点退出。
七、验证与回退
7.1 实际验证结果
| 检查项 | 本次结果 |
|---|---|
| Gitea 健康端点 | 返回 200 |
| 登录页 | 显示 DoraTiger Auth,并保留本地密码登录表单 |
| 匿名 OIDC 请求 | 完整跳转到 DoraTiger 登录流程,页面返回 200 |
| 原用户关联 | 已完成,并确认仍为原账号 |
| 认证源改名 | 保留原认证源 ID,原关联记录仍存在 |
| 自动注册配置 | 修改后重启,持久配置保留 |
| 本地注册页 | 没有本地密码注册表单 |
| 原有用户、组织及仓库 | 数量与变更前一致 |
| 新用户首次登录及个人建仓 | 尚未完成实际验收 |
新用户验收应使用一个没有 Gitea 关联的测试身份:先不加入访问组检查拒绝,再加入组检查首次登录自动建号;之后确认不是管理员、能创建个人仓库、默认私有,且再次登录不会重复创建账号。该过程不能用“登录页出现按钮”替代。
7.2 回退范围
需要撤销自动注册时,恢复变更前 app.ini 并重启 Gitea。配置回退不会删除期间已经创建的用户,应另行核对这些账号。
如果整个 OIDC 接入需要暂停,先确认本地管理员登录可用,再在 Gitea 禁用认证源,并按需要停用 Authentik 应用。保留关联和配置便于排查;不要直接删除并重建认证源,更不要为撤销几项设置恢复整库,覆盖期间新增的仓库和用户数据。
八、配置问题与解答
8.1 点击关联后返回主页
Q:选择认证源后直接回到 Gitea 主页,没有看到关联成功,是邮箱不同吗?
本次原因不是邮箱。初次创建 Authentik Provider 时,grant_types 为空,Gitea 发出的授权码请求被拒绝,回调带有 error=invalid_request,关联没有建立。
处理时编辑 doratiger-truenas-gitea,在 Grant types 中启用 Authorization code 并保存,然后重新发起关联。修复后请求进入 DoraTiger 登录流程,最终完成原账号绑定。通过 API 或脚本创建 Provider 时,不能假定所有字段都会自动获得界面向导里的预选值。
排查应查看从 Gitea 发出请求到回调的完整跳转,以及 Authentik 对应事件。不要公开完整授权 URL、Cookie 或授权码。只看到第一跳 307 到 Authentik 域名,不能证明请求已经被接受。
8.2 认证源名称与品牌不一致
Q:关联列表显示 authentik,能改成 DoraTiger Auth 吗?
可以,但 Gitea 认证源名称还参与生成回调路径。本次保留原认证源 ID,在原记录上改名,同时把 Authentik 严格回调从示例中的:
text1https://git.example.com/user/oauth2/authentik/callback
改为:
text1https://git.example.com/user/oauth2/DoraTiger%20Auth/callback
操作顺序是先在 Authentik 增加新回调,再编辑 Gitea 原认证源名称;验证新路径后,删除旧回调。这样既保留账号关联,也避免改名期间只有旧地址可用。
本次验证了登录页名称、实际发送的 redirect_uri 以及到达登录流程的完整路径,原关联记录仍在。新接入可直接使用最终品牌名称,无须先创建一个名为 authentik 的认证源。
8.3 邮箱是否必须统一
Q:把 Authentik 邮箱改成 Gitea 邮箱,是否就能自动关联?
本次没有这样做。使用原 Gitea 账号发起关联,再验证 Authentik 身份即可。邮箱是用户资料,修改它可能影响通知及其他应用;不必为了这一个应用修改整个身份中心的邮箱。
8.4 自动注册与访问限制
Q:既然自动注册打开,是否所有 Authentik 用户都能进入 Gitea?
还要经过应用上的访问组绑定。只有允许访问此应用的身份才能继续认证;Gitea 再根据已有绑定或自动注册设置选择用户处理路径。需要同时检查两端,不能只看注册开关。
参考
支付宝
微信