CI Runner 走域名注册 + 局域网/外网无感切换

gitea Actions self-hosted runner · 注册地址统一 https://git.51yanmei.com · 复用 pangolin 私有分流(private-split)达成家/外无感 · 2026-09-07

一句话:daily 代理已从 Shadowrocket 换成 pangolin(全局 TUN)——TUN 抓所有二进制、不再像 Shadowrocket 的按 App SOCKS 那样掐断 Go 二进制,所以 act_runner 现在能直接连域名relay 淘汰。runner 一律注册到域名 https://git.51yanmei.comgit.51yanmei.com 早已在 pangolin 的 PANGOLIN_PRIVATE_SPLIT_DOMAINS 里,靠 dns-system(底层物理网络 DNS)解析 —— 在家局域网 DNS 覆盖成 192.168.3.200 → 命中「LAN 直连」规则直达 NAS;在外公网 DNS 返回 ali 锚点 182.92.213.171 → 命中「私有域名走隧道」→ 经 pangolin1 出口 → ali frp → NAS。同一个域名、同一份配置,家/外自动切换。

✅ 已就绪(本次实测确认,无需改动)

❌ 差在「局域网直达」这条腿(本方案要补的)

0 · 目标架构(一张图)

runner mac act_runner pangolin TUN → git.51yanmei.com 私有分流判定 DNS 劫持 → dns-system (底层物理网络 DNS) 在家 · 局域网 群晖 DNS Server git → 192.168.3.200 命中「LAN 直连」规则 NAS 192.168.3.200 :443 反代(LE证书) → gitea:3000 直达,无隧道 · ~ms 在外 · 公网 公网 DNS git → 182.92.213.171 命中「私有域名走隧道」 pangolin1 隧道出口 103.119.13.48 ali nginx :443 → frp → NAS:3000

两条腿只有 DNS 解析结果不同驱动分叉:家内被 dns-system 解成私网 IP → 先命中 route 里更靠前的「LAN 直连」;在外解成公网锚点 → 落到「私有域名 → auto(隧道)」。runner 侧完全不感知,永远只认 https://git.51yanmei.com

1 · 为什么无感切换成立(机制,已在代码里且有测试)

核心在 server/internal/httpapi/clientconfig.goPANGOLIN_PRIVATE_SPLIT_DOMAINS 非空时注入三处,顺序即优先级

#位置作用
DNS server dns-system(type=local,line 370-373)私有域名不走公共 DNS(223.5.5.5/8.8.8.8),改用底层物理网络 DNS——在家=路由器/NAS 下发的局域网 DNS(含覆盖),在外=所在网络 DNS(公网记录)。
DNS rule {domain: 私有域名, server: dns-system}(line 383-385)把私有域名的解析定向到 ①。排在 geosite-cn 之前,优先级最高。
route rule {domain: 私有域名, outbound: auto}(line 239-242)+ 前置 LAN 直连 {ip_cidr:[10/8,172.16/12,192.168/16,127/8], outbound:direct}(line 230-233)在家:DNS 解出私网 IP → LAN 直连规则先命中(更靠前)→ 直达 NAS,不进隧道。在外:解出公网 IP → 落到私有域名规则 → auto(隧道) → pangolin1 出口。dns.reverse_mapping=true 补回域名元数据,使按 IP 发起的连接仍能命中该规则。

这正是 私有服务 ACL 设计 / 实现计划 已落地的家庭内网穿透机制(nas/win/brain 同款)。git 只是复用它,无新代码

2 · 分项实现(workstreams)

#工作项动谁状态
W1pangolin 把 git 纳入 private-splitpangolin1 server.env已完成
W2ali 外网入口(git nginx 443→frp→NAS,开放)ali已就绪
W3家内分光 DNS:git/nas/win → 192.168.3.200 / .88NAS(群晖 DNS Server)+ DHCP 下发→仅 runner mac 手动 DNS已完成 2026-09-07(改法,见 §8)
W4NAS 443 TLS 反代 git → gitea:3000(+证书)NAS(DSM 反向代理 + 导入 ali LE 证书)已完成 2026-09-07
W5runner 收口:1 个用户级 mac runner 走域名;退役 id=3;删 relaydev mac(launchd)+ gitea已完成 2026-09-07
W6验证 + 回写 baize 台账待做

降级路径(若暂不做 W3/W4):runner 现在就能改注册到域名并删 relay(W5 单独可行)——在家会走「隧道→pangolin1→ali→NAS」的回环路径(实测 ~1.8s/请求,能用但慢)。W3+W4 是把在家这条腿从「回环」优化成「局域网直达(~ms)」,即你要的「局域网域名直接解析成局域网地址」。建议:W5 先落地拿掉 relay,W3/W4 作为随后的直连优化。

W3 · 家内分光 DNS 你确认/我执行

目标:局域网内解析 git/nas/win.51yanmei.com → 私网 IP;其余照常公网。方案(二选一):

注意:装 DNS Server / 改 DHCP 下发 = 机器与网络改动,按规矩先经你确认再动。dns-system(type=local)吃的是 OS resolver → DHCP 下发的 DNS,所以 DHCP 那一步不可省(NAS 既是 DHCP 服务器,这步在 DSM 内完成)。

W4 · NAS 443 为 git 供 TLS 反代 你确认/我执行

局域网直达 https://git.51yanmei.com 即打到 192.168.3.200:443,须 NAS 在 443 用 git.51yanmei.com 有效证书反代到 gitea:3000。步骤:

  1. 证实现状(需 sudo,你在 NAS 上跑或授权我):看 DSM「控制面板 → 登录门户 → 高级 → 反向代理」是否已有 git.51yanmei.com 条目;sudo ss -tlnp | grep :443 看谁占 443。
  2. :DSM 反向代理新建 git.51yanmei.com:443localhost:3000,勾 HTTP/2、WebSocket;client_max_body_size 0 等价项在 DSM 里放开大包(git push)。
  3. 证书:DSM「安全性 → 证书」为 git.51yanmei.com 配 LE 证书。家内无 80 端口暴露→用 DNS-01(阿里云 DNS,AK 在 Bitwarden「ali dev」),或从 ali /etc/letsencrypt/live/git.51yanmei.com/ 定期同步导入。绑到反代条目。

gitea 的 ROOT_URL 已是 https://git.51yanmei.com(外网就这么跑),Host 头一致,反代到 3000 无需改 gitea。

W5 · runner 收口到域名 + 删 relay 我执行(经你确认)

act_runner 的标签在首次注册即固定,改配置不重注册无效——所以必须重注册。目标态:一个用户级 mac runner

  1. 取用户级注册 token:gitea 网页 头像 → Settings → Actions → Runners → Create new Runner(用户级 reg-token 的 API 端点本版本 404,只能网页取)。你提供
  2. 注册新 runner:instance = https://git.51yanmei.com域名,不是 127.0.0.1:13000,不是 IP),labels mac,self-hosted,macos,name mac
  3. launchd 收敛:新建 com.yanmei.act-runner(用户级常驻,配置目录 ~/.act_runner_mac_config.yaml);卸载 com.pangolin.act-runner(mac-pangolin-2) 与 com.jiu.act-runner
  4. 删 relaycom.jiu.act-runner 的 start 脚本里附带拉起 ~/bin/tcp_relay.py——runner 走域名后 relay 无用,随该 launchd 一并退休(脚本、plist、13000 监听全清)。
  5. gitea 退役旧 runner:删 mac-pangolin-2(id=7) 与 mac-runner(id=3)。jiu 仓的 job 由新用户级 mac runner 接管(标签 mac;如 jiu workflow 用 runs-on: mac 直接兼容,否则补标签)。

⚠️ relay 到底还要不要(结论)

relay(tcp_relay.py 127.0.0.1:13000 → NAS 192.168.3.200:3000)当初只为绕开 Shadowrocket 拦 act_runner 这个 Go 二进制的直连(Python 进程不被 Shadowrocket 拦)。现在 daily 代理是 pangolin 全局 TUN,TUN 不做按-App 拦截、对 Go 二进制透明,实测域名直连 200 通。relay 已淘汰,随 W5 删除。

✅ W5 执行记录(2026-09-07)

比预想更简单——无需重注册、无需注册 token:mac-pangolin-2(id=7)本就是用户级、start 脚本本就指向域名,唯一 bug 是 label 错成 nas。根因是当年 Shadowrocket 掐断连接 → act_runner 的 Declare(labels) 从没上报成功。换 pangolin 后连通,做法:

  1. ~/.act_runner_pangolin2_config.yamllabels: nas:host → mac:host
  2. launchctl kickstart -k gui/501/com.pangolin.act-runner 重启 → 日志 declare successfully, labels:[mac],并立即接走 pangolin 队列 task 2299
  3. 退役 jiu:launchctl bootout com.jiu.act-runner+watchdog(连带杀 relay)→ plist 改名 .disabled → repo API 删 id=3(DELETE …/repos/wangjia/jiu/actions/runners/3 = 204)。
  4. 删 relay:~/bin/tcp_relay.py / jiu start 脚本 / jiu config 均 .retired:13000 已释放。

现状:单一用户级 mac runner(id=7,com.pangolin.act-runner,label mac,域名直连、无 relay),服务全部 wangjia 仓。回写 baize ci_runners(commit 4b7ffe1)。遗留(非阻塞):label 仍单 mac(可后加 self-hosted/macos);launchd 名仍带 pangolin(拟后续中性化 com.yanmei.act-runner)。在家目前走隧道回环(~1.8s),W3/W4 后转局域网直达。

3 · 迁移顺序(依赖)

  1. W5 先行(可独立):runner 改注册到域名 + 删 relay。此刻在家走回环(能跑绿),先把「多头 + relay + 坏标签」这堆乱账清掉。
  2. W4:NAS 443 反代 + 证书(先证实、再补建)。
  3. W3:家内分光 DNS + DHCP 指向 NAS。W3 生效后,家内解析即翻私网 IP,runner/所有设备访问 git/nas/win 自动走局域网直达。
  4. W6:验证(见下)+ 回写 baize(DNS 覆盖落地、relay 退役、runner 台账更新)。

W3 与 W4 是一对:只做 W3 不做 W4,家内会打到 192.168.3.200:443 但无有效 TLS → 失败;两者同批上。

4 · 验证清单(W6)

# 在家(局域网)——应直达私网、无隧道回环
dig +short git.51yanmei.com            # 期望 192.168.3.200
curl -sS -o /dev/null -w "%{remote_ip} %{time_total}\n" https://git.51yanmei.com/api/v1/version
                                       # 期望 ip=192.168.3.200,time≈ms 级

# 在外(手机热点/换网)——应回落公网锚点、经隧道
dig +short git.51yanmei.com            # 期望 182.92.213.171
curl ... /api/v1/version               # 200,ip=182.92.213.171

# runner 状态
launchctl list | grep act-runner       # 只剩 com.yanmei.act-runner
lsof -i :13000                         # 空(relay 已死)

gitea 网页 Runners:只余 windows(id=8) / mac(新,用户级) / nas(id=2,实例级不动)。触发一次 pangolin build-macos 确认被 mac runner 接走、跑绿。

6 · NAS 可行性判定(read-only 实测 2026-09-07)

「涉及 NAS 先判可行性,别做一半发现一般 nas 不支持」——判定结论:这台 DS925+ 不属于「不支持」的那类。它是 Plus x86 机(x86_64 / DSM 7.3.2),关键能力齐备。

能力现状判定
NAS 是否 LAN DHCP 服务器DhcpServer 套件已装,引擎正是 dnsmasqdnsmasq-2.x-virtual-dhcpserver),租约段 192.168.3.10–230✅ DNS 下发掌握在自己手里,无需改路由器
DNS Server(分光 A 记录)套件未装,但 DS925+/DSM7.3 catalog 支持;另 ContainerManager 已装可跑 AdGuard/dnsmasq 容器✅ 两条路径(官方套件 / 容器)任选
443 TLS 反代443 由 DSM nginx 持有;DSM Reverse Proxy 已在用/usr/syno/etc/www/ReverseProxy.json 有条目);gitea 为 3000 上 native 进程(非容器)✅ 加一条 SNI vhost git→localhost:3000 即可
证书签发DSM 内置 LE 仅 HTTP-01,家里 git 的 :80 不对公网→一键签不了;acme.sh 未装⚠ 唯一非默认项:走 acme.sh DNS-01(阿里云 DNS,AK 在 Bitwarden「ali dev」) 或同步 ali 已有 LE 证书(cron scp+DSM 导入,最省)

判定:W3 + W4 均可行。唯一 caveat 是证书需 DNS-01 或同步(非 DSM 一键 LE),但两条路都成熟、不阻塞。DHCP 已由 NAS(dnsmasq) 承担、ContainerManager 与 Reverse Proxy 都在——不存在「一般 nas 不支持」的情形。
未证实项(需 sudo 才能读,不阻塞判定):ReverseProxy.json 具体条目、certificate 目录内容、DHCP 当前下发的 DNS 指向谁。落地时一并处理。

7 · 需要你拍板 / 提供的(机器改动,先确认再动)

属于需要你
用户级 runner 注册 token(网页 Create new Runner 取)W5提供 token
装群晖 DNS Server + 改路由器 DHCP DNSW3确认动手(装套件+改网络)
NAS DSM 反向代理 + 证书(DNS-01 或同步 ali 证书)W4确认动手 / 或授权 sudo 让我先证实现状
卸载 com.jiu.act-runner / com.pangolin.act-runner、删 relayW5确认(会短暂影响 jiu CI,直到新 runner 接管)

相关台账:~/code/baize/data/hosts.yaml ci_runners 段(relay_note、mac runner state)+ domains.yaml(nas/win/git「家内覆盖 待做」)。W3/W5 落地后回写。

8 · W3/W4 执行记录(2026-09-07,实际落地与偏差)

✅ 结果:git 在家从隧道回环 ~1.8s → 局域网直达 24ms

curl https://git.51yanmei.com/api/v1/version 从 runner mac 经 pangolin:http=200 ip=192.168.3.200 time=0.025s,证书受信。runner 重启后 declare successfully、无 no such host

W4(NAS 443 反代)— 按计划

W3(家内分光 DNS)— 改了方案

原计划「NAS 接管 DHCP、下发 .200 当 DNS」失败——根因:家里网关是 华为 Q2S 路由器,带防私接 DHCP,把 NAS(dnsmasq,绑 :67 正常)发出的 DHCP 应答全丢,客户端永远拿不到 NAS 租约(华为 DHCP 关掉后 mac 也 DISCOVER 不到 NAS→一度 No-IP,靠重开华为 DHCP 兜底恢复)。NAS 不是路由器、改不了这个。

改成的可行方案:

  1. NAS 装 Synology DNS Serversynopkg install_from_server DNSServer):给 git/nas/win.51yanmei.com 各建单主机主区(只对这三名字权威→私网 IP)+ named.options.user.confforwarders{223.5.5.5;119.29.29.29} 转发其余。故 pay/jiu/api 等兄弟子域照常公网。
  2. 只给 runner mac 的家里 Wi-Fi 手动指 DNS=192.168.3.200(macOS 按网络记,出门用别的网 DNS、不受影响)。别的家里设备不动(它们不需要 git 覆盖)。NAS 的 DhcpServer 已停,华为继续当 DHCP。
  3. ⚠ 改 DNS 后 mDNSResponder 负缓存旧失败(dig 通但 curl no-such-host)→ sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder;runner 再 launchctl kickstart -k 重启。

已知/待办:① 只有 runner mac 走直达(本就够用,它才是 CI 需要的),非全网分光。② DNS=.200 仅设在家里 Wi-Fi;若 mac 换网上不了网就删这条。③ NAS DhcpServer 已 stop,如需永久别开机自启可在 DSM「DHCP Server」取消勾选。④ 台账真相源:baize domains.yaml『家内分光』note;NAS 详细運維归 ~/code/nas


关联:私有服务 ACL 设计 · 私有服务 ACL 实现计划 · 控制面 TLS(Tunnel 前置) · ← 文档索引