本文记录一次在 Linux 主机上从源码部署 Tailscale 自定义 DERP Server 的完整过程。部署使用
vfox管理 Go,并交由用户级 systemd 管理。
最终监听端口如下:
| 服务 | 协议 | 默认监听端口 | 手动修改后端口 |
|---|---|---|---|
| http-port | 证书挑战或跳转 | 80 | -1(关闭) |
| DERP | HTTPS/TCP | 443 | 8443 |
| STUN | UDP | 3478 | 3478 |
本文显式关闭 derper 的辅助 HTTP 监听,只保留 HTTPS 8443 和 STUN 3478。自定义 HTTPS 端口通过 DERP Map 的
DERPPort声明。
1. 部署环境与重要限制
部署前确认以下条件:
- 已安装golang环境,本文使用 vfox+Golang 插件。
- TCP 8443、UDP 3478 当前没有被其他服务占用。
端口占用可以先检查:
ss -ltnup | rg ':(3478|8443)\b'
开始之前,需要了解自定义 DERP 的几个限制:
- DERP 服务本身必须使用 HTTPS,客户端通过 HTTP Upgrade 建立双向通道。
- 本配置需要放行 HTTPS 8443、STUN 3478 和 ICMP。
- 当前服务未启用客户端校验。任何知道公网 IP 和 Map 参数的人都可以把它加入自己的 tailnet,存在带宽滥用和流量费用风险。
详细要求参见 Tailscale Custom DERP Servers 官方文档。
本文主机位于 NAT 后方,因此采用端口转发。这是官方不支持的实验性拓扑:本机验证正常不代表公网 DERP 可用,在完成公网 HTTPS、STUN 和真实中继测试前,不应视为生产部署完成。
2.安装 Golang 环境
Golang 环境自行参考官网教程
可使用Vfox工具进行安装和版本控制
vfox install golang
vfox use golang
3. 编译 derper
官方文档通常建议安装最新版:
go install tailscale.com/cmd/derper@latest
检查版本和编译器:
/opt/derp-servers/bin/derper --version
go version -m /opt/derp-servers/bin/derper
验证编译产物:
derper --version: 1.102.2-ERR-BuildInfo
module: tailscale.com v1.102.2
Go: go1.26.5
SHA-256: bed842649072fa85d08840aaf8ad6662689993bc46d4c4fb4f0fa89733cd008c
-ERR-BuildInfo 是使用 go install 构建时该命令自身显示的版本后缀;准确的模块版本以 go version -m 输出为准。
4. 创建 derper-user 用户并安装到目录
创建用户
useradd \
--system \
--user-group \
--create-home \
--home-dir /home/derper-user \
--shell /usr/sbin/nologin \
--comment "Tailscale DERP service account" \
derper-user
创建程序、状态和用户 unit 目录:
install -d -o derper-user -g derper-user -m 0755 \
/home/derper-user/.local/bin \
/home/derper-user/.local/share/derper \
/home/derper-user/.config/systemd/user
三个目录的用途:
/home/palworld/.local/bin
存放 derper 可执行文件。/home/palworld/.local/share/derper
存放 DERP 节点私钥、TLS 证书及 DERP Map。/home/palworld/.config/systemd/user
存放 palworld 的 systemd 用户服务配置。
安装二进制:
install -o derper-user -g derper-user -m 0755 \
/opt/derp-servers/bin/derper \
/home/derper-user/.local/bin/derper
安装域名证书(可选)
如果80 443端口可使用,可让程序自动申请证书。
手动安装证书方法:derper 的 manual 模式按 <hostname>.crt 和 <hostname>.key 查找文件,因此安装时需要给证书改名,并严格限制私钥权限:
chown derper-user:derper-user \
/home/derper-user/.local/share/derper/example.com.crt \
/home/derper-user/.local/share/derper/example.com.key
chmod 0644 /home/derper-user/.local/share/derper/example.com.crt
chmod 0600 /home/derper-user/.local/share/derper/example.com.key
5. 创建 systemd 用户服务
创建 /home/derper-user/.config/systemd/user/derper.service:
[Unit]
Description=Tailscale custom DERP server
Documentation=https://tailscale.com/docs/reference/derp-servers/custom-derp-servers
After=default.target
[Service]
Type=simple
ExecStart=/home/derper-user/.local/bin/derper -c /home/derper-user/.local/share/derper/derper.key -a :8443 -http-port -1 -stun-port 3478 -certmode manual -hostname example.com -certdir /home/derper-user/.local/share/derper
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=default.target
自动申请证书配置,需要授予绑定 80/443 的权限,只需要开通端口就可以自动完成证书申请
如果使用普通用户的 systemd --user 运行 需要 授予二进制低端口权限
sudo setcap cap_net_bind_service=+ep /home/derper-user/.local/bin/derper
ExecStart=/home/palworld/.local/bin/derper \
-c /home/palworld/.local/share/derper/derper.key \
-a :443 \
-http-port 80 \
-stun-port 3478 \
-certmode letsencrypt \
-hostname cuu.blackbullet.cn \
-certdir /home/palworld/.local/share/derper/certs \
-acme-email your-email@example.com
主要参数说明:
| 参数 | 作用 |
|---|---|
-c | 持久化 DERP 节点私钥;非 root 运行时该参数必填 |
-a :8443 | 在 TCP 8443 提供 DERP HTTPS 服务 |
-http-port -1 | 完全关闭辅助 HTTP 监听 |
-stun-port 3478 | STUN 服务监听 UDP 3478 |
-certmode manual | 使用手动安装的本地证书链和私钥 |
-hostname example.com | TLS 证书和 DERP Map 使用的服务器域名 |
-certdir ... | 保存 TLS 证书和私钥 |
由于服务只监听高端口,用户 unit 不需要 root 权限或额外 capability。DERP Map 中的 DERPPort 必须与 -a 保持一致,否则客户端仍会尝试连接默认 HTTPS 443。
6. 启用用户服务与开机自启
确保 derper-user 即使没有登录会话,用户级 systemd 也能在开机后持续运行:
loginctl enable-linger derper-user
/run/user/<UID> 必须由 systemd-logind 创建,不能用 mkdir 手工替代。下面通过 id -u derper-user 动态取得 UID,避免假定所有主机上 derper-user 都是 UID 1001。
重新加载并启动服务:
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user daemon-reload
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user enable --now derper.service
如果已经登录到 derper-user 的 Shell,可以直接使用:
systemctl --user enable --now derper.service
首次启动时,derper 会自动生成并持久化 DERP 节点身份私钥:
/home/derper-user/.local/share/derper/derper.key
TLS 文件则是前一步安装的:
/home/derper-user/.local/share/derper/example.com.crt
/home/derper-user/.local/share/derper/example.com.key
derper.key 和 TLS 私钥用途不同,但都必须持久化并限制访问权限。
7. 可选步骤-配置 DERP Map (给 Tailscale用的)
将以下内容合并到 Tailscale tailnet policy:
自定义 Region ID 应使用 Tailscale 预留的 900~999 范围。随后进入 Tailscale 管理后台的 Access controls/policy 编辑器,合并并保存配置,等待控制平面把新 Map 下发到客户端。
{
"derpMap": {
"Regions": {
"900": {
"RegionID": 900,
"RegionCode": "custom-derp",
"RegionName": "Custom DERP",
"Nodes": [
{
"Name": "custom",
"RegionID": 900,
"HostName": "example.com",
"IPv4": "27.151.72.226",
"IPv6": "none",
"DERPPort": 8443
}
]
}
}
}
}
9. 验证部署
检查服务状态
systemctl --user --no-pager --full status derper.service
应看到:
Active: active (running)
检查监听端口
ss -ltnup | rg ':(3478|8443)\b'
应能看到:
- TCP 8443 由
derper以 TLS/HTTPS 监听。 - UDP 3478 由
derper监听。
10. 日常运维
查看实时日志:
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
journalctl --user -u derper.service -f
重启服务:
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user restart derper.service
停止服务:
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user stop derper.service
确认开机自启和运行状态:
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user is-enabled derper.service
runuser -u derper-user -- \
env XDG_RUNTIME_DIR=/run/user/"$(id -u derper-user)" \
systemctl --user is-active derper.service
loginctl show-user derper-user -p Linger
预期分别为 enabled、active 和 Linger=yes。