流量路径
┌──────────────────────────────────────────────────────────┐
│ tailscale serve HTTPS 流量路径 │
│ TLS 在 max2 本机终结 · 不经过云端转发 │
├──────────────────────────────────────────────────────────┤
│ arm Hermes Agent │
│ opencode --attach https://max2-at...:4096 │
│ │ │
│ ▼ │
├──────────────────────────────────────────────────────────┤
│ ① WireGuard 隧道(P2P 直连) │
│ 端到端加密 · 同局域网直连 · 不经云端 │
│ │ │
│ ▼ │
├──────────────────────────────────────────────────────────┤
│ ② max2 本机 tailscale serve │
│┌────────────────────────────────────────────────────────┐│
││ HTTPS :4096(TLS 卸载) ││
││ Let's Encrypt 证书 · 本地终结 ││
││ 解密后转发到 localhost ││
│└────────────────────────────────────────────────────────┘│
│ │ │
│ ▼ │
├──────────────────────────────────────────────────────────┤
│ ③ opencode serve :4096(HTTP) │
│ localhost 本地服务 · 纯 HTTP │
│ 收到的是 tailscale serve 解密后的请求 │
│ │ │
│ ▼ │
├──────────────────────────────────────────────────────────┤
│ 结果:Hermes 通过 HTTPS 安全连接 │
│ WireGuard 不可窃听 + TLS 不可篡改 │
│ 双层加密,纵深防御 │
└──────────────────────────────────────────────────────────┘背景
opencode serve 默认只提供 HTTP 服务。在 tailnet 内通过 WireGuard 传输已经加密,HTTP 裸连在现有架构下是安全的。但如果出于纵深防御、策略合规或工具兼容性需要 HTTPS,有以下方案。
核心约束:域名 max2-at.tail9e6317.ts.net 只对 tailnet 内节点可解析,公开 ACME 挑战不可用。Tailscale 通过自己的 ACME DNS 挑战协议签发 Let's Encrypt 证书。
方案 A:tailscale serve(推荐)
Tailscale 内置 serve 命令,自动绑 Let's Encrypt 证书,一行完成 TLS 卸载。
流量路径:
Hermes ──[Tailscale HTTPS :4096]── tailscale serve ──[HTTP localhost]── opencode操作步骤(max2 PowerShell):
# 1. 先注册 tailscale serve,--bg 不阻塞,立即返回
tailscale serve --bg --https 4096 http://127.0.0.1:4096
# 2. 同一个窗口继续启动 opencode serve(阻塞打印日志)
opencode serve --print-logs --hostname 127.0.0.1 --port 4096验证:
tailscale serve status清理:
tailscale serve --https 4096 off
tailscale serve reset之后 Hermes 连接 https://max2-at.tail9e6317.ts.net:4096/,Tailscale 自动处理 TLS 证书。
注意: --https 4096 指定的是对外暴露的 HTTPS 端口,http://127.0.0.1:4096 是实际提供服务的地址,两者端口一致即可。老版命令 tailscale serve --https 4096 / http://127.0.0.1:PORT 中用 / 分隔的语法已被新版移除。
| 特性 | 说明 |
|---|---|
| 证书管理 | 全自动,Tailscale 处理续期 |
| 配置量 | 一行命令,零维护 |
| 依赖 | 仅 Tailscale(已安装) |
方案 B:Caddy + tailscale cert
如果 tailscale serve 的行为不满足需求,Caddy 是备用方案。
# 1. 安装 Caddy
scoop install caddy
# 2. 获取 Tailscale 证书(Tailscale 内部处理 ACME DNS-01 挑战)
tailscale cert max2-at.tail9e6317.ts.net
# 在当前目录生成 cert.pem + key.pem
# 3 个月有效期,Tailscale 会自动续期
# 3. 写 Caddyfile
https://max2-at.tail9e6317.ts.net:4096 {
tls /path/to/cert.pem /path/to/key.pem
reverse_proxy 127.0.0.1:58407
}
# 4. 启动 Caddy
caddy run| 特性 | 说明 |
|---|---|
| 证书管理 | 半自动,需手动 cert 命令,Tailscale 自动续期文件 |
| 配置量 | 一个 Caddyfile,适合高级场景 |
| 依赖 | 需装 Caddy |
| 适用场景 | 需要额外中间件、路径重写、请求过滤等 |
方案 C:stunnel + tailscale cert
stunnel 是经典的 TLS 隧道工具。
# 1. 获取证书
tailscale cert max2-at.tail9e6317.ts.net
# 2. 写 stunnel.conf
[https-service]
accept = 4096
connect = 127.0.0.1:58407
cert = cert.pem
key = key.pem
# 3. 启动 stunnel
stunnel stunnel.conf| 特性 | 说明 |
|---|---|
| 证书管理 | 需手动 cert,Tailscale 自动续期文件 |
| 配置量 | 一个 .conf 文件 |
| 依赖 | 需装 stunnel |
| 适用场景 | 最小化依赖,仅做 TLS 隧道 |
方案选型建议
| 场景 | 推荐 | 理由 |
|---|---|---|
| 日常 opencode 开发 | 不配 HTTPS | WireGuard 传输加密已够用,设好 PASSWORD + ACL 即可 |
| 纵深防御 / 合规要求 | tailscale serve | 一行命令,零维护,TLS 卸载 |
| 需要中间件处理 | Caddy | 反向代理 + TLS 一体,灵活 |
| 纯隧道,最小依赖 | stunnel | 仅做 TLS,不改应用层 |
常见疑问
打开 Serve 后流量会走 Tailscale 云端转发吗?
不会。 Tailscale Serve 的 TLS 证书在 max2 本机上终止,流量路径不变:
arm Hermes
│
▼
┌──────────────────────────────────┐
│ WireGuard 隧道 │
│ (P2P 直连 / 不经过 Tailscale 云) │ ← 与不开 Serve 完全一致
└──────────────────────────────────┘
│
▼
max2 本机
├── tailscale serve(TLS 卸载) ← 本地完成
│ HTTPS → HTTP 解密转发
│
└── opencode serve :4096(HTTP)| 不开 Serve (HTTP) | 开 Serve (HTTPS) | |
|---|---|---|
| 传输层 | WireGuard 加密 | WireGuard + TLS |
| 网络路径 | P2P 直连 / DERP 中继 | P2P 直连 / DERP 中继(不变) |
| TLS 终结位置 | 无 | max2 本机 |
| 云端处理业务流量 | 否 | 否 |
HTTPS 的密钥交换和卸载都在 max2 本地完成,相当于在 WireGuard 隧道上面加了一层 TLS,两层的加解密都是本地节点之间的事。证书拉取和续期通过 Tailscale 控制面走 ACME DNS-01,不与业务流量路径重叠。
需要先在管理后台开启
首次使用 tailscale serve 会提示:
Serve is not enabled on your tailnet.
To enable, visit:
https://login.tailscale.com/f/serve?node=xxxx点链接到 Tailscale 管理后台开启 Serve 开关即可,一次开启,后续不再提示。
注意
- HTTPS 解决的是传输通道加密和身份验证,不代替应用层认证。无论用哪个方案,
OPENCODE_SERVER_PASSWORD必须设置 - tailscale cert 签发的 Let's Encrypt 证书 90 天有效期,Tailscale 会自动在到期前重新拉取到
%ProgramData%\Tailscale\certs\ - tailscale serve 本质是本地代理 + TLS 卸载,opencode serve 本身仍以 HTTP 绑定 localhost,外界通过 HTTPS 端口访问时,Tailscale 解密转发到本地 HTTP 端口
- 新版 tailscale serve 的
--https语法不带/分隔:tailscale serve --bg --https 4096 http://127.0.0.1:PORT - 先跑
tailscale serve --bg注册转发(不阻塞),再跑opencode serve阻塞看日志,同一个窗口完成