|
| 1 | +# Tailscale DERP Template |
| 2 | + |
| 3 | +这个目录提供仓库内默认的自建 DERP 入口,替代共享 `docker-compose.yml` 里的旧 `derper` 服务。 |
| 4 | + |
| 5 | +目录职责: |
| 6 | + |
| 7 | +- `compose.yaml` |
| 8 | + 作用:定义 `tailscaled-auth` 与 `derper` 两个服务。 |
| 9 | +- `Dockerfile.derper` |
| 10 | + 作用:构建并运行 `cmd/derper`,避免继续依赖外部第三方 `derper` 镜像。 |
| 11 | +- `.env.example` |
| 12 | + 作用:给出推荐默认值;你通常只需要额外补公网 IP 与 `TS_AUTHKEY`。 |
| 13 | +- `tailnet-policy.derp.example.hujson` |
| 14 | + 作用:提供可直接改 IP 和端口后合并进 tailnet policy 的 `derpMap` 模板。 |
| 15 | +- `start.ps1` |
| 16 | + 作用:统一封装常用 `docker compose` 操作,避免每次手写长命令。 |
| 17 | + |
| 18 | +## 设计说明 |
| 19 | + |
| 20 | +- `tailscaled-auth` 只负责登录 tailnet、维护 state 和暴露 `tailscaled.sock` |
| 21 | +- `derper` 通过 `--verify-clients` + `tailscaled.sock` 把访问范围限制在当前 tailnet |
| 22 | +- `derper` 使用 `network_mode: host` |
| 23 | + 原因:官方不建议把 DERP 放在 NAT 后面,而 Docker bridge 的 `ports:` 发布本质上就是一层 NAT |
| 24 | +- `derper` 使用 `--certmode=manual --certdir=/var/lib/derper/certs` |
| 25 | + 当 `DERP_PUBLIC_IP` 是 IP 且 `certdir` 里没有对应 `<IP>.crt/.key` 时,当前 `cmd/derper` 会自动生成自签 IP 证书 |
| 26 | + |
| 27 | +## 启动前准备 |
| 28 | + |
| 29 | +1. 复制环境变量模板: |
| 30 | + |
| 31 | +```bash |
| 32 | +cp config/network/tailscale/derp/.env.example config/network/tailscale/derp/.env.local |
| 33 | +``` |
| 34 | + |
| 35 | +2. 编辑 `config/network/tailscale/derp/.env.local` |
| 36 | + |
| 37 | +至少填写: |
| 38 | + |
| 39 | +- `DERP_PUBLIC_IP` |
| 40 | +- `TS_AUTHKEY` |
| 41 | + |
| 42 | +3. 确认宿主机防火墙已放行: |
| 43 | + |
| 44 | +- `TCP 80` |
| 45 | +- `TCP 443` |
| 46 | +- `UDP 3478` |
| 47 | + |
| 48 | +## 启动 |
| 49 | + |
| 50 | +推荐命令: |
| 51 | + |
| 52 | +```bash |
| 53 | +docker compose --env-file config/network/tailscale/derp/.env.local -f config/network/tailscale/derp/compose.yaml --project-directory config/network/tailscale/derp up -d --build |
| 54 | +``` |
| 55 | + |
| 56 | +如果你习惯 PowerShell,也可以直接用: |
| 57 | + |
| 58 | +```powershell |
| 59 | +./config/network/tailscale/derp/start.ps1 |
| 60 | +``` |
| 61 | + |
| 62 | +常用命令: |
| 63 | + |
| 64 | +```bash |
| 65 | +docker compose --env-file config/network/tailscale/derp/.env.local -f config/network/tailscale/derp/compose.yaml --project-directory config/network/tailscale/derp logs -f derper |
| 66 | +docker compose --env-file config/network/tailscale/derp/.env.local -f config/network/tailscale/derp/compose.yaml --project-directory config/network/tailscale/derp ps |
| 67 | +docker compose --env-file config/network/tailscale/derp/.env.local -f config/network/tailscale/derp/compose.yaml --project-directory config/network/tailscale/derp down |
| 68 | +``` |
| 69 | + |
| 70 | +对应的 `start.ps1` 用法: |
| 71 | + |
| 72 | +```powershell |
| 73 | +./config/network/tailscale/derp/start.ps1 |
| 74 | +./config/network/tailscale/derp/start.ps1 logs --tail 100 |
| 75 | +./config/network/tailscale/derp/start.ps1 ps |
| 76 | +./config/network/tailscale/derp/start.ps1 pull |
| 77 | +./config/network/tailscale/derp/start.ps1 config |
| 78 | +./config/network/tailscale/derp/start.ps1 -DryRun |
| 79 | +``` |
| 80 | + |
| 81 | +## 证书行为 |
| 82 | + |
| 83 | +默认 `DERP_CERTS_DIR=./certs`。第一轮启动时: |
| 84 | + |
| 85 | +- 如果目录里已经有 `${DERP_PUBLIC_IP}.crt` 和 `${DERP_PUBLIC_IP}.key`,`derper` 会直接使用它们 |
| 86 | +- 如果目录为空,且 `DERP_PUBLIC_IP` 是 IP,`derper` 会自动生成一对自签 IP 证书 |
| 87 | + |
| 88 | +这也是当前仓库里 `Set-TailscaleDerp.ps1` 仍然输出 `InsecureForTests = true` 的原因之一:第一版模板默认走 |
| 89 | +IP-only + 自签证书路线。 |
| 90 | + |
| 91 | +## 写入 tailnet policy |
| 92 | + |
| 93 | +容器启动后,再用仓库脚本把同一个公网 IP 写进 tailnet policy: |
| 94 | + |
| 95 | +```powershell |
| 96 | +./scripts/pwsh/network/tailscale/Set-TailscaleDerp.ps1 ` |
| 97 | + -ServerIp 203.0.113.10 ` |
| 98 | + -DerpPort 443 ` |
| 99 | + -StunPort 3478 ` |
| 100 | + -PolicyPath ./tailnet-policy.hujson |
| 101 | +``` |
| 102 | + |
| 103 | +如果你是直接在 Admin Console 的 JSON editor 里改,可以只生成片段: |
| 104 | + |
| 105 | +```powershell |
| 106 | +./scripts/pwsh/network/tailscale/Set-TailscaleDerp.ps1 ` |
| 107 | + -ServerIp 203.0.113.10 ` |
| 108 | + -DerpPort 443 ` |
| 109 | + -StunPort 3478 ` |
| 110 | + -PrintSnippet |
| 111 | +``` |
| 112 | + |
| 113 | +如果你更喜欢先改现成模板,再手动合并到 tailnet policy,也可以从这里开始: |
| 114 | + |
| 115 | +`config/network/tailscale/derp/tailnet-policy.derp.example.hujson` |
| 116 | + |
| 117 | +## 验证 |
| 118 | + |
| 119 | +模板检查: |
| 120 | + |
| 121 | +```bash |
| 122 | +DERP_PUBLIC_IP=203.0.113.10 TS_AUTHKEY=tskey-example docker compose -f config/network/tailscale/derp/compose.yaml --project-directory config/network/tailscale/derp config |
| 123 | +``` |
| 124 | + |
| 125 | +客户端侧排查: |
| 126 | + |
| 127 | +- `tailscale netcheck` |
| 128 | +- `tailscale ping <另一台设备>` |
| 129 | +- `tailscale debug derp` |
| 130 | + |
| 131 | +## 注意事项 |
| 132 | + |
| 133 | +- `--verify-clients` 只能限制到 tailnet 级,不能进一步细分“同 tailnet 内哪些设备允许走这个 DERP” |
| 134 | +- 如果你把 `derper` 和 `tailscaled-auth` 固定到不同 Tailscale 版本,官方当前不保证 `--verify-clients` 路径稳定可用 |
| 135 | +- 如果你后续有稳定域名,可以继续沿用这个目录结构,再把 manual cert 路线切换到域名证书方案 |
0 commit comments