Headscale搭建-前端、服务、自定义derp
目的:在日常的办公使用中尤其是软件开发的一些情况,经常会遇到同步代码服务器在公司,不对外网公开的一些状况;或者使用的一些使用公司内部文件在内部服务器上,在外网无法访问。需要与内网服务器进行组网,目前可用的有openvpn、frp、wiregurd、tailscale等工具可以使用。经过考虑使用tailscale进行组网,考虑到速度及传输问题,使用开源控制工具headscale作为控制端搭建,使用官网的derper工具搭建个人derp。只介绍操作及踩坑,无各个软件说明
1 Headscale搭建
1.1 程序获取
自己编译
从headscale的github仓库下载源码,自己下载golang进行编译,具体编译过程再次就不写,若只想部署不要选择改方法
下载现成的二进制程序
直接从headscale的官方github仓库下载编译好的headscale二进制程序,选择合适的版本下载。
1.2 部署
添加执行权限
介绍采用的是程序直接部署,没有使用docker的方式部署,部署在linux服务器上,主要原因headplane只能在linux上运行,云服务器为linux系统
以0.27.1版本为例进行介绍
获得headscale的二进制文件headscale_0.27.1_linux_amd64后执行以下命令,
1 | sudo cp headscale_0.27.1_linux_amd64 /usr/local/bin/headscale |
配置文件
创建配置目录
1 | $ mkdir -p /etc/headscale |
路径 /etc/headscle/config.yaml
主要修改的几项配置
server_url修改为公网ip或者域名,中国大陆访问域名必须备案,访问地址listen_addr前面加上http://
listen_addr 监听地址若不使用域名需要改为 0.0.0.0:port
建议开启随机客户端端口,将 randomize_client_port 设为 true。
prefixes.v4 根据使用的主机数量进行调整子网掩码原始值 为100.64.0.0/10 , # Tailscale/Headscale 默认使用的 CGNAT 地址空间一部分 使用的的类似于中国移动宽带的NAT网段 ,设置的ip必须在100.64.0.0/10的网段内,具体的可以在https://ipjisuanqi.com/网站上计算一下

dna.magic_dns 个人建议为false 不适用虚拟的域名直接访问, 简单解释1一下,若主机名xxxx1, base_domain为example.com,则其他客户端可以通过xxxx1.example.com访问
1 |
|
创建文件夹用于存储数据和证书
1 | $ mkdir -p /var/lib/headscale |
创建空的 SQLite 数据库文件:
1 | $ touch /var/lib/headscale/db.sqlite |
踩坑点
- 若想使用https千万不要自签名证书,目前tailscale客户端对于自签名证书无法链接。若要使用需要导入ca证书到系统中为可信任,本人没试过
系统服务文件
路径/etc/systemd/system/headscale.service
下面文件是拿官方仓库提供的进行修改的文件内容
1 | [Unit] |
启动headscale
创建 headscale 用户:用以上服务文件必须创建用户
1 | $ useradd headscale -d /home/headscale -m |
修改 /var/lib/headscale 目录的属主:
1 | $ chown -R headscale:headscale /var/lib/headscale |
修改配置文件/etc/headscale/config.yaml中的unix_socket` 路径:
1 | unix_socket: /var/run/headscale/headscale.sock |
Reload SystemD 以加载新的配置文件:
1 | $ systemctl daemon-reload |
启动 Headscale 服务并设置开机自启:
1 | $ systemctl enable --now headscale |
查看运行状态:
1 | $ systemctl status headscale |
查看 Headscale 占用的端口(默认为 8080 HTTP, 9090 gRPC, 50443 Prometheus metrics,具体取决于您的配置):
1 | $ ss -tulnp | grep headscale |
headscale 相关命令
创建用户
1 | $ headscale users create default |
1 | $ headscale users create test -d testA -e aaa@xxx.com |
2 Tailscale接入Headscale
目前主流系统均支持接入headscale,手头只有linux、windows、安装、iPhone,只对这四种进行了测试
登陆坑点
命令行登陆注意 --user USERID填写的是用户id
2.1 linux系统接入
直接下载官方的的tailscale二进制文件,或者配置好官方的软件包仓库后直接用管理工具安装本文用管理工具安装
具体的配置操作见官方https://tailscale.com/download/linux
命令行安装

管理库安装选择合适的版本后按照步骤操作即可

安装完成后直接 启动并设置服务开机自启
1 | $ systemctl start tailscaled && systemctl enable tailscaled |
链接命令
1 | # 在自己的服务器上部署的 Headscale,请将 <HEADSCALE_PUB_ENDPOINT> 替换为您的 Headscale 公网 IP 或域名,并注意协议 (http/https) 和端口 |
这里推荐将 --accept-dns=false 选项加上,以避免 Headscale 的 MagicDNS 设置覆盖系统默认 DNS,除非您确实需要并已正确配置了 Headscale 的 DNS 功能。执行完上面的 tailscale up 命令后,终端会显示一个注册链接:
1 | To authenticate, visit: |
浏览器访问后会让在服务器上执行一条命令 执行完毕即可连接成功

2.2 安卓机接入使用的为1.92.3版本
可以找网上其他人发的apk安装包,大陆境内应用商店没有
点击右上角的人物

点击Acount


输入服务器地址即可

点击 Add account后会弹出浏览器显示内容如下 ,也是需要在服务器运行指令

成功后返回tailscale即可看到类似下面的页面

2.3 windows接入
安装坑点
安装的时候可能会安装失败,在其日志中找到一个含.msi的链接直接复制到浏览器下载 msi格式的为真正的安装程序。
接入方式
打开 windows终端直接运行(直接运行原因,tailscale不改变安装路径的时候会把执行的路径自动加入环境变量)
1 | tailscale up --login-server=http://<HEADSCALE_PUB_ENDPOINT>:8080 --accept-routes=true --accept-dns=false |
同样会在终端窗口展示一个链接,复制到浏览器访问后即可看到需要在服务器执行的命令
2.4 IOS
ios下载需要一个非中国大陆的icloudid
安装完毕按照下图操作即可,其余步骤和安卓相同



2.5 headplan允许的方式
点击Add device 选择Register Machine Key


在弹出的界面输入网页弹出页面中 –key后面的所有内容,注意去掉首尾空格,选择owner之后点击Confirm即可

2.6 预授权接入的方式
获得密钥
使用以下命令为用户id为1的用户创建一个有效期1小时的预授权密钥
1 | $ headscale preauthkeys create -u 1 -e 1h |
headplane获取预授权密钥
登陆后点击Add Device Generate Pre-auth Key


根据需求选择用户及时间
Reuseable为密钥是否可以重复使用
Ephemeral为客户端登录后在登出就会被移除设备,在登陆需要重新认证

linux和windows
获得密钥后在原来的登陆命令后拼接上一个空格在拼接(linux和windows)
1 | --authkey=获得的密钥 |
则登陆命名就变为 注意相关信息替换成自己的。
1 | $ tailscale up --login-server=http://<HEADSCALE_PUB_ENDPOINT>:8080 --accept-routes=true --accept-dns=false --authkey=获得的密钥 |
ios和安卓
在输入自定义服务器后不要管弹出的网页关掉,返回tailscale,按找之前步骤找到如下界面即可点击 Use an auth key

把获得的authkey填写点击Add account即可

3 headplane 安装
headplane 为headscale的管理前端
个人使用起来比headscale-admin、headscale-ui更为方便、headscale-admin 编译后有bug需要调整源码重新编译使用,再此只介绍headplane
headplane 有两种运行方式 一种是docker运行一种是编译后运行
两种运行方式选择
若是比较新的系统则可以直接选择编译运行的方式,前提是GCC版本要大于2.17,也可以使用docker 运行,国内下载镜像速度慢酌情考虑docker
若为centos7 等比较古早的版本无法直接编译运行 需要使用docker 容器运行
不想使用官方的 固定访问路径/admin ,需要自己编译或者自己打包docker 镜像
修改访问路径
在项目根目录下找到react-router.config.ts vite.config.ts``vitest.config.ts三个文件把里面的 /admin 修改为 /你想要的名称
配置文件运行宿主机上
路径/etc/headplane/config.yaml
需要修改的配置headscale.url headscale.config_path 按照实际情况配置server.cookie_secure 该配置若无ssl需要配置为false 否则无法正常登陆
1 | # Configuration for the Headplane server and web application |
3.1 docker运行
自己打包镜像
从官方headplaned的github仓库克隆下主线代码
进行docker构建 前提(已经安装完golang和nodejs及pnpm)
先修改Dockerfile文件 添加golang的国内镜像
1 | FROM --platform=$BUILDPLATFORM golang:1.25.1 AS go-base |
进入克隆下的项目根目录 构建镜像
1 | $ docker build --build-arg IMAGE_TAG=0.6.1 -t headplane-custom:0.6.1 . |
确认:
1 | $ docker images | grep headplane |
导出为 tar 包: 文件很大可以自己压缩,本人懒得压缩(该步骤针对于服务器GCC版本低无法在服务器上构建镜像)
1 | $ docker save headplane-custom:0.6.1 -o headplane-custom-0.6.1.tar |
把文件拷贝到服务器上(该步骤针对于服务器GCC版本低无法在服务器上构建镜像)
目标机器导入镜像
1 | $ docker load -i headplane-custom-0.6.1.tar |
验证:
1 | $ docker images | grep headplane |
该种方式的的compose 文件为
1 | services: |
官方镜像
用 Docker 运行 Headplane 非常简单,只需应用一个 compose 文件:
1 | services: |
直接使用运行即可 file.yaml替换成自己compse文件名
1 | docker compse -f file.yaml up -d |
注意把docker切换成国内的源
3.2 自己编译运行
默认nodejs相关环境安装完毕
1 | $ git clone https://github.com/tale/headplane.git |
配置service文件
路径/etc/systemd/system/headplane.service
1 | [Unit] |
运行指令
1 | $ systemctl daemon-reload |
3.3 headplane登陆管理控制台
在浏览器中输入地址http://你的域名:你的端口/你编译headplane时修改的名或者官方用的用admin,如若启用ssl则需要使用https://
根据提示使用
1 | $ headscale apikeys create |
创建密钥,密钥有效期默认90天 输入后点击signin即可

登陆成功的页面,右上角用户那点击会显示剩余密钥可用时间。

4 certbot构建证书配置ssl https 访问
前提安装完成nginx,有一个备案的域名 或 可用域名
个人倾向于使用Let’s Encrypt申请免费证书,设置好自动续期即可
服务器需要访问公网一个可以解析的域名本文以example.com为例
Certbot 是由 Electronic Frontier Foundation (EFF) 提供的一个开源工具,用于自动化从 Let’s Encrypt 获取和管理 SSL 证书。Certbot 会自动为你处理证书申请、安装和续期等过程。
使用linux snap 包管理工具安装Certbot,支持snap后可以使用如下命令安装Certbot
1 | $ sudo snap install --classic certbot #安装Certbot |
也可用自带的yum或者dnf或apt安装
4.1 证书申请,申请单域名
泛域名认证较为复杂需要域名提供商的域名解析api暂不提供改方式
nginx 配置 一定要放80端口aaa.xxxxx.com解析到服务器
1 | server { |
申请证书
1 | $ certbot certonly --cert-name my-headscale-cert -d aaa.xxxxx.com |
基本能申请成功,证书路径在
/etc/letsencrypt/live/my-headscale-cert 文件下,该文件夹下文件为软连接用此即可
证书续期
首先,你可以手动测试续期是否正常:
1 | sudo certbot renew --dry-run |
如果没有报错,可以继续配置自动续期任务:
1 | sudo crontab -e |
在打开的编辑器中添加
1 | #每10天执行一次自动续期任务凌晨三点 |
4.2 nginx 的ssl配置
1 | server { |
5 DERP的部署
derp需要自己编译目前需要强制域名ssl ,可以参考Tailscale 基础教程:部署私有 DERP 中继服务器 · 云原生实验室修改源码进行ip部署
第一种方式获取
1 | $ go install tailscale.com/cmd/derper@latest |
第二种方式获取
GitHub - tailscale/tailscale: The easiest, most secure way to use WireGuard and 2FA.
从tailscale的仓库中拉取代码
进入cmd/derper目录下运行
1 | $ go build . |
把编译好的derper二进制文件复制到/usr/local/bin目录下
1 | $ cp derper /usr/local/bin/derper |
编辑service文件
路径/etc/systemd/system/derper.service hostname 替换成自己域名,–a尽量使用443端口其余配置尽量不要动
关键配置说明--verify-clients=true 这个为客户端需要认证防止DERP被白嫖的关键设置。
1 | [Unit] |
把第4部申请的证书做软连接供derper使用 ,因此可以与headscale 管理使用同一个域名 –certdir即为证书路径 ,derper只接收路径不接受文件 软连接的名一定和域名相同
1 | $ ln -s /etc/letsencrypt/archive/my-headscale-cert/fullchain1.pem /etc/derper/aaa.xxxx.cn.crt |
运行以下指令
1 | $ systemctl daemon-reload |
配置到headscale
有以文件的防止配置
配置路径为/etc/headscale/derp.yaml
regioncode 和 regionname两个可以自定义命名 derpport为开放的端口
1 | regions: |
headscale配置修改,为了防止连接tailscale的derp 建议修改成以下
1 | #urls: [] |
重启headscale服务
服务器开放端口
443 tcp
8443 tcp
3478 udp
DERP防止被别人白嫖
在启动参数中添加 --verify-clients=true
DERP的服务器安装 tailscale 作为认证客户端使用
DERP服务器的tailscale登陆命令
1 | $ tailscale up \ |
关键参数解释
--netfilter-mode=off不插 iptables防止服务器无法访问外网 不动 FORWARD / OUTPUT
--shields-up=true 不影响服务器原有网络, 防止局域网内其他主机访问
--accept-routes=false 不接受路由防止局域网其他主机通过内网ip访问服务器
6 打通内网
内网中转服务器目前只在linux系统上实验成功,windows暂未实验成
在这台 Linux 主机 (例如 OpenWrt) 上,需要开启内核的 IP 转发功能
1 | $ echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/ipforwarding.conf |
在需要转发的内网主机上宣告路由,如果之前已运行,可以加上 --reset 参数重新配置,如果您有多个局域网段需要宣告,可以用逗号分隔,例如 --advertise-routes=192.168.1.0/24,10.0.0.0/8。
假设内网ip为192.168.1.X 子网为255.555.255.0 即24位子网掩码计算,子网掩码需要转换为二进制
1 | # 将 <HEADSCALE_PUB_ENDPOINT> 替换为您的 Headscale 服务器地址 |
headscale 服务器启用宣告的路由设置
如果使用 Headscale 命令行操作,可以先找到路由节点的 ID 或名称
1 | $ headscale nodes list-routes |
查看需要启用的节点id路由是否在 Approved
若不在 以2号为例 进行允许
1 | $ headscale nodes approve-routes --identifier 2 --routes 192.168.124.0/24 |
验证
1 | $ headscale nodes list-routes |
headplane操作
选择有蓝色 Subnets字样的节点按下图操作

按照如下操作即可 可以看到Subnets上的感叹号没了

可能出现的坑点
--accept-routes=true 若在内网内其他机器也登陆的tailscale 则其他机器的改选项一定要设置为false 否则可能会在成内网其他机器的路由表混乱,导致无法通过内网ip来访问登陆tailscale的主机
7 判断是直连还是经过DERP
在终端机上 使用tailscal ping 另一台终端机 若结果不含 DERP则为直连

iperf测速 受限于公网的上传和下载,跨服务商也会有差距。能通的话基本不会有太大问题。除非网络提供商锁P2P传输。


非直连自己的DERP测速 受限于公网带宽 经过路由中转后速度也会降

8 参考文章
Tailscale 基础教程:Headscale 的部署方法和使用教程 · 云原生实验室
Tailscale 基础教程:部署私有 DERP 中继服务器 · 云原生实验室
使用 Let’s Encrypt 免费申请泛域名 SSL 证书,并实现自动续期 - 平元兄 - 博客园
至此部署完成!有问题欢迎联系邮箱 wzy9212@163.com
- 标题: Headscale搭建-前端、服务、自定义derp
- 作者: WangZeyu
- 创建于 : 2026-01-26 14:47:08
- 更新于 : 2026-01-27 10:34:13
- 链接: https://wangzeyu92.github.io/2026/01/26/Headscale搭建-前端、服务、自定义derp/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。