海外云服务器搭建 Headscale 自建 Tailscale 控制服务器完整教程:零配置组网,把家里、办公室和云上的机器连成一张虚拟内网(2026最新版)

📅 · ChengziCloud - 一站式云端服务

Meta Description: 手把手教你在海外云服务器上从零搭建 Headscale——Tailscale 控制服务器的开源自建实现。无需公网 IP、无需开放端口,就能把家里 NAS、云服务器、笔记本和手机零配置连成一张加密虚拟内网(Tailnet)。含 Ubuntu/Debian 安装、config.yaml 逐项详解、内置 Let's Encrypt 自动签发证书、MagicDNS 域名访问、子网路由、Exit Node 出口节点、ACL 访问策略、备份升级与 14 条常见问题 FAQ。

> 关键词:headscale教程、headscale搭建、Tailscale自建控制服务器、零配置组网、mesh VPN、内网穿透、海外云服务器搭建、MagicDNS、子网路由、Exit Node、ACL策略、DERP中继

前言

如果你手上不止一台机器,大概率已经体会过这种割裂感:一台腾讯云轻量放着自己的博客,一台 AWS 跑着测试环境,家里的群晖 NAS 存着全家照片,办公室还有一台旧主机当开发机,再加上随身的两台笔记本和一部手机。它们各自都在网络上,却彼此"看不见"——想从笔记本连一下家里的 NAS,得先记住运营商的动态公网 IP,还得在路由器上映射端口;想从云服务器回连家里的开发机,大概率连不上,因为家里根本没有公网 IPv4。

传统的解法有两类,但都很累。第一类是"端口映射":frp、Nginx 反代,本质是把内网的某个端口搬到一台有公网 IP 的中转机上。它适合"发布服务给公网访问",可一旦你想让机器与机器之间互相直连,就得为每一个方向都配一条隧道,节点一多配置量呈平方级增长。第二类是"手写 VPN":WireGuard 本身极好、极快、极简洁,但它的设计假设是你知道每个节点在哪里——你得手工维护每一台机器的公钥、内网地址和公网端点,网络里每加一台机器,就要在所有对端上补一段配置。

问题的本质是:我们缺少的是一个"组网层",而不是又一条"隧道"。 我们希望的是——每台机器只做一次接入动作,剩下的自动完成:自动发现彼此、自动穿透 NAT、自动分配地址、自动做身份认证和访问控制、自动给每台机器一个好记的域名。

这正是 Tailscale 干的事,而它的控制服务器(control server)是整个体系里唯一闭源的部分。Headscale 就是它的开源自建替代:一个用 Go 写的、单二进制、默认用 SQLite 存储的控制服务器,官方仓库目前已收获 4.4 万颗星(juanfont/headscale)。有了它,你可以完全脱离 Tailscale 的官方账号体系,用自己的域名、自己的服务器、自己的数据库,搭出一张只属于你和你的团队的虚拟内网(官方称之为 tailnet)。

一句话总结本教程要做的事:在一台海外云服务器上装好 Headscale,然后用 tailscale up 把散落各地的机器"接"进来,它们就自动连成了一张能互相直连、能互相用域名访问的加密内网。

> 💡 部署建议:Headscale 对服务器配置要求极低,一台最便宜的入门 VPS 就够跑。推荐用阿里云国际版 / AWS / 腾讯云国际版部署——国际线路访问更稳、无需备案。通过 5.chengzicloud.cloud 购买可享专属折扣。

一、Headscale 到底是什么?它回答的是哪个"另一个问题"

先把名词讲清楚,避免和站内其他几篇网络文章混淆。

Tailscale 不是传统 VPN,而是一个"覆盖网络(overlay network)"。 它底层仍然是 WireGuard——负责真正加解密数据包的还是 WireGuard 那套极其高效的协议;但 Tailscale 在它之上加了一层"协调层",负责三件事:

1. 交换公钥:把网络里所有节点的 WireGuard 公钥互相交换,这样任意两个节点无需预先配置就能加密通信; 2. 分配地址:给每个节点自动分配一个 100.64.0.0/10 网段(CGNAT 段)内的 IPv4 地址和一个 fd7a:115c:a1e0::/48 段内的 IPv6 地址; 3. 下发路由与策略:告诉客户端哪些网段可以走哪条路(子网路由 / 出口节点),以及谁可以访问谁(ACL)。

承担这三件事的服务器就叫控制服务器。Tailscale 官方的控制服务器是闭源的 SaaS,而 Headscale 就是它的开源复刻——它扮演的角色是"公钥交换点 + 地址分配器 + 策略下发中心"。注意:数据流量并不过 Headscale。节点之间在可能的情况下会走 NAT 穿透后的点对点直连,只有直连失败时才回落到中继服务器(DERP)。所以 Headscale 这台机器几乎不吃带宽,只吃一点点 CPU 和数据库 IO。

那它和站内已经写过的几篇网络教程,到底区别在哪?下面这张边界表把它们放在同一张坐标系里,读者可以一眼看清"谁解决什么":

| 方案 | 它回答的核心问题 | 前提条件 | 主要代价 | | --- | --- | --- | --- | | frp 内网穿透 | 把内网的某个端口/服务"搬到"公网,供外部访问 | 必须有一台带公网 IP 的中转机,且要对外开放端口 | 每加一个服务就要配一条隧道;需维护泛域名与证书 | | Cloudflare Tunnel | 没有公网 IP、一个入站端口都不开,也能把服务发布出去 | 需要一个 Cloudflare 账号和托管在 CF 的域名 | 连接方向只出站;国内访问速度不受控 | | WireGuard | 建立点对点的加密隧道 | 需要手动维护每个对端的公钥与端点,或自建一台 hub | 节点数量一多,配置复杂度急剧上升 | | Headscale | 一堆机器各在各的 NAT 后面,想零配置组成一张互相直连的网 | 需要一台有公网 IP 的服务器来跑控制服务器 | 控制服务器本身是单点,需要备份 |

再补两条反向边界,避免误用:

- 它不是"翻墙工具"。 虽然可以用 Exit Node 让流量从某台机器出去,但它的定位是"把你自己名下的机器连起来",不是公共代理服务。请遵守所在地法律法规,仅用于访问你自己的资源。 - 它不替代反代和证书。 内网里服务用什么域名、什么 TLS 证书,仍然是 Nginx/Caddy 的事;Headscale 只负责让机器之间"能互相到达",并给出 MagicDNS 域名解析。

理解了这层定位,下面就可以动手了。

二、服务器配置推荐与价格对比

Headscale 之所以适合"随便一台小机器就能跑",是因为它把复杂度都留给了客户端,服务端只做轻量的协调工作:一个 Go 静态二进制、一个 SQLite 数据库、一块放密钥和证书的小目录。官方的运行要求非常克制:

- 一台拥有公网 IP 的服务器(推荐 IPv4 + IPv6 双栈); - 能通过 HTTPS 的 443 端口对外提供服务(Tailscale 客户端在某些场景下硬编码假定 443 端口); - 一个较新的 Linux 或 BSD 系统; - 一个专用的本地用户来运行 headscale(官方 DEB 包会自动创建 headscale 用户); - 一点点命令行基础。

也就是说,1 核 1G 的入门机型就完全够用。真正决定你花多少钱的,不是 Headscale 本身,而是这台机器"顺便"还要干点什么——比如当你需要它同时承担 DERP 中继(帮别人穿透 NAT)、或者跑一台 Exit Node 让流量从它出去时,带宽和流量包才成为成本大头。

下表给出几档常见配置的建议用途:

| 配置 | 适用场景 | 说明 | | --- | --- | --- | | 1 核 / 1G 内存 / 25G 硬盘 | 纯控制服务器,10 台以内节点 | 最省钱的方案,官方最低要求即可 | | 2 核 / 2G 内存 / 50G 硬盘 | 控制服务器 + MagicDNS + 小规模 ACL | 推荐起点,留出内存余量 | | 2 核 / 4G 内存 / 80G 硬盘 | 顺带开内置 DERP + 当一台 Exit Node | 需要留意流量包,DERP 中转会消耗带宽 | | 4 核 / 8G 内存 / 160G 硬盘 | 团队使用(几十节点)+ 多个子网路由 | 中大型 tailnet 的稳妥选择 |

主流海外云厂商单机价格对比

下面两张表分别是 DigitalOcean Droplet 和 AWS Lightsail 的官方常规档位(均为当日直读官网定价页采集)。两者都适合跑 Headscale,按自己惯用的厂商选即可:

DigitalOcean Droplet(Basic 共享型)

| 内存 | vCPU | 自带流量 | SSD | 价格(美元/月) | | --- | --- | --- | --- | --- | | 512 MiB | 1 | 500 GiB | 10 GiB | $4 | | 1 GiB | 1 | 1000 GiB | 25 GiB | $6 | | 2 GiB | 1 | 2000 GiB | 50 GiB | $12 | | 2 GiB | 2 | 3000 GiB | 60 GiB | $18 | | 4 GiB | 2 | 4000 GiB | 80 GiB | $24 | | 8 GiB | 4 | 5000 GiB | 160 GiB | $48 | | 16 GiB | 8 | 6000 GiB | 320 GiB | $96 |

AWS Lightsail(Linux 计划,含 1 个月免费试用)

| 内存 | vCPU | 自带流量 | SSD | 价格(美元/月) | | --- | --- | --- | --- | --- | | 0.5 GB | 2(突发型) | 1 TB | 20 GB | $5 | | 1 GB | 2(突发型) | 2 TB | 40 GB | $7 | | 2 GB | 2(突发型) | 3 TB | 60 GB | $12 | | 4 GB | 2 | 4 TB | 80 GB | $24 | | 8 GB | 2 | 5 TB | 160 GB | $44 | | 16 GB | 4 | 6 TB | 320 GB | $84 | | 32 GB | 8 | 7 TB | 640 GB | $164 |

> 声明:本文价格数据采集于 2026 年 10 月,仅为公开官网参考区间,实际价格随区域、促销与计费方式浮动,请以各家官网结算页为准;金额单位均为美元(USD)。阿里云国际版与腾讯云国际版的同类轻量/云服务器通常有各自的新用户优惠,价格区间请以官网实时页面为准。

> 💡 选型提示:如果你只做"自建内网",$5~$6 档的入门机型足矣,把钱花在域名和流量上更划算。想一站式对比各家海外云厂商的配置与折扣,可访问 5.chengzicloud.cloud 查看当前可用的优惠方案。

你还需要准备什么

- 一个域名:Headscale 必须通过 HTTPS 提供服务,强烈建议给控制服务器配一个独立子域名,例如 hs.example.com。 - 域名解析权:需要在 DNS 里把 hs.example.com 的 A/AAAA 记录指向这台服务器的公网 IP(注意:Tailscale 客户端直连控制服务器时用的是真实 IP,因此 A 记录不能指向 Cloudflare 代理,必须是 DNS only / 灰云)。 - 防火墙放行端口:TCP 443(必需)、TCP 80(若用内置 Let's Encrypt 的 HTTP-01 验证)、UDP 3478(若开启内置 DERP,用于 STUN)。其余端口一律不用对外开。这一点和 frp/隧道类方案相比,暴露面非常小。

准备好了,我们进入实战。

三、实战部署:十步跑通 Headscale

以下步骤以 Ubuntu 22.04 / 24.04 或 Debian 12 为例(官方 DEB 包支持这两个及更新版本),全部命令可直接复制执行。示例中统一使用域名 hs.example.com,请替换成你自己的子域名。

第一步:系统初始化与前置检查

先更新系统、装好基础工具,并确认防火墙对外的端口策略。Headscale 只需要 443,量入为出地把其它端口关掉即可:

`bash sudo apt update && sudo apt upgrade -y sudo apt install -y curl wget gnupg ca-certificates `

确认服务器的公网 IP 与 DNS 解析一致(这一步很关键,稍后签证书会用到):

`bash curl -4 ifconfig.me dig +short hs.example.com A `

两条命令输出的 IP 必须相同。若不一致,先回到域名服务商把 hs.example.com 的 A 记录改为仅 DNS(不要开 CDN 代理),再继续。

如果你用的是云厂商的安全组/防火墙,请放行 TCP 443(若开启内置 DERP 再放行 UDP 3478)。如果在服务器上还开了 ufw,可这样放行:

`bash sudo ufw allow 443/tcp sudo ufw allow 3478/udp `

第二步:安装 Headscale(官方 DEB 包,推荐)

官方推荐的安装方式是 DEB 包,它会自动创建运行用户、附带默认配置和 systemd 服务文件,省去手工折腾。先到 GitHub Releases 页面确认最新版本号(本教程撰写时最新稳定版为 v0.29.4),然后下载安装:

`bash HEADSCALE_VERSION="0.29.4" HEADSCALE_ARCH="amd64" wget --output-document=headscale.deb \ "https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb" sudo apt install ./headscale.deb `

安装后验证服务是否起来(此时用的是默认配置,先不管它能否对外服务):

`bash sudo systemctl status headscale headscale version `

官方的示例配置文件放在 /usr/share/doc/headscale/examples/config-example.yaml,可以拿来对照。

第三步:编写 config.yaml(逐项讲清关键设置)

配置文件默认位于 /etc/headscale/config.yaml。Headscale 会按 /etc/headscale → ~/.headscale → 当前目录的顺序查找 config.yaml。修改后可用 headscale configtest 校验语法,再重启生效。

下面是一份精简可用的生产配置,请把域名和 IP 换成你自己的:

`yaml server_url: https://hs.example.com listen_addr: 0.0.0.0:8080 metrics_listen_addr: 127.0.0.1:9090 grpc_listen_addr: 127.0.0.1:50443 grpc_allow_insecure: false trusted_proxies: []

noise: private_key_path: /var/lib/headscale/noise_private.key

prefixes: v4: 100.64.0.0/10 v6: fd7a:115c:a1e0::/48

derp: server: enabled: false region_id: 999 region_code: "headscale" region_name: "Headscale Embedded DERP" verify_clients: true stun_listen_addr: "0.0.0.0:3478" private_key_path: /var/lib/headscale/derp_server_private.key automatically_add_embedded_derp_region: true urls: - https://controlplane.tailscale.com/derpmap/default paths: [] auto_update_enabled: true update_frequency: 3h

database: type: sqlite sqlite: path: /var/lib/headscale/db.sqlite write_ahead_log: true wal_autocheckpoint: 1000

acme_url: https://acme-v02.api.letsencrypt.org/directory acme_email: "[email protected]" tls_letsencrypt_hostname: "hs.example.com" tls_letsencrypt_cache_dir: /var/lib/headscale/cache tls_letsencrypt_challenge_type: HTTP-01 tls_letsencrypt_listen: ":http"

log: level: info format: text

policy: mode: file path: ""

dns: magic_dns: true base_domain: vpn.example.com override_local_dns: true nameservers: global: - 1.1.1.1 - 1.0.0.1 split: {} search_domains: [] `

几个必须理解的字段:

- server_url:客户端连接控制服务器用的地址,必须和你签发的证书域名完全一致(这里是 https://hs.example.com)。填错会导致客户端一直转圈连不上。 - listen_addr:Headscale 本地监听地址。设为 0.0.0.0:8080 表示监听所有网卡,交由它自己处理 TLS;如果你打算用 Nginx 反代,则改回 127.0.0.1:8080 并让反代终止 TLS。 - prefixes:节点地址分配范围。注意官方警告:这些前缀必须是 Tailscale 标准网段的子集(IPv4 只能用 100.64.0.0/10 的 CGNAT 段,IPv6 只能用 fd7a:115c:a1e0::/48 的 ULA 段),越界会导致"诡异且难排查"的故障。 - derp.server.enabled: false:默认关闭内置 DERP。先关着,用官方免费的 DERP 中继地图(urls 里的那行),等节点都连通了再按需自建。 - database.type: sqlite:官方明确建议用 SQLite,Postgres 仅为历史遗留而保留,所有新开发都以 SQLite 为目标。所以别折腾数据库,一个文件就是全部状态。 - tls_letsencrypt_hostname:填你的域名,Headscale 会自动向 Let's Encrypt 申请并续期证书,无需再装 certbot。 - dns.base_domain:MagicDNS 的域名后缀,必须与 server_url 的域名不同(否则冲突)。例如控制服务器是 hs.example.com,这里就用 vpn.example.com。

第四步:用内置 Let's Encrypt 自动签发证书

上一步的配置填好后,Headscale 会自动完成证书申请——这是它相比"手写 WireGuard + 手动签证书"的一大省心之处。记得先确保 80 和 443 端口没有被 Nginx/Apache 占用:

`bash sudo systemctl restart headscale sudo systemctl status headscale `

观察日志,看到成功监听 HTTPS 即可:

`bash sudo journalctl -u headscale -n 30 --no-pager `

最后验证健康检查端点(这是官方推荐的连通性判据):

`bash curl https://hs.example.com/health `

返回 {"status":"pass"} 之类的健康响应,就说明控制服务器已经在公网上正常服务了。如果只返回超时,八成是 DNS 解析、防火墙端口或证书没签成,按 journalctl 的报错逐一排查。

第五步:创建用户与预授权密钥

Headscale 的模型里,"节点"归属于一个"用户"。默认只有 headscale 用户或 root 能访问 Unix socket(/var/run/headscale/headscale.sock),记得加 sudo。先建一个用户:

`bash sudo headscale users create myorg sudo headscale users list `

然后生成一个预授权密钥(pre-auth key),用于让客户端非交互式接入。默认有效期 1 小时、且只能用一次:

`bash sudo headscale preauthkeys create --user myorg `

命令会返回一串 hskey-auth-... 开头的密钥,先复制保存,第六步要用。若想一次性批量接入多台机器,可以加参数调整有效期与可复用次数(用 sudo headscale preauthkeys create --help 查看全部选项)。

第六步:把客户端接入内网(Linux / Windows / macOS / 手机)

接入的通用公式只有一句话:把 --login-server 指向你的 Headscale 地址。以 Linux 为例,官方一键脚本安装 Tailscale 客户端:

`bash curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up --login-server https://hs.example.com --authkey hskey-auth-你的密钥 `

把上一步生成的密钥填进 --authkey,回车后稍等几秒,客户端就会自动注册并出现在你的 tailnet 里。回到服务器上核对:

`bash sudo headscale nodes list `

其它平台:

- Windows:从 Tailscale 官网下载安装包,安装后在右下角托盘图标右键 → "Preferences/首选项",或在命令行里执行 tailscale up --login-server https://hs.example.com --authkey <密钥>。 - macOS:从 App Store 或官网下载 App,同样在设置中指定自定义登录服务器(部分版本需使用 standalone 版客户端)。 - Android / iOS:安装 Tailscale App,首次登录时选择"使用其它服务器(Use an alternate server)",填入 https://hs.example.com,再完成授权。

如果某台设备不方便用密钥,也可以走网页授权流程:客户端执行 tailscale up --login-server https://hs.example.com 后会打印一个 Auth ID 和一个授权链接,你在服务器上执行下面这条命令审批即可:

`bash sudo headscale auth register --user myorg --auth-id <AUTH_ID> `

第七步:开启 MagicDNS,用域名代替 IP 访问

节点注册完成后,你会看到一个 100.64.x.x 的地址。但没人愿意记 IP。开启 MagicDNS 后,每台机器都能用 主机名.你的base_domain 直接访问。这一步其实在第三步的配置里已经开好了(magic_dns: true 且设了 base_domain: vpn.example.com),你要做的是确保客户端接受了 DNS:

`bash sudo tailscale set --accept-dns=true `

之后,假设有一台主机名叫 nas,你就能直接在浏览器或 SSH 里用 nas.vpn.example.com 访问它——前提是客户端启用了 --accept-dns(Tailscale 客户端默认开启)。你还可以在 dns.extra_records 里手工补 DNS 记录,把某个内网服务的域名直接指到某台节点的 100.64.x.x 地址,配合本机 Nginx 反代,就能像访问公网站点一样访问内网服务:

`yaml dns: extra_records: - name: "grafana.vpn.example.com" type: "A" value: "100.64.0.3" `

修改后重启 Headscale 生效,用 dig +short grafana.vpn.example.com 验证解析是否正确。

第八步:子网路由,把整个局域网"拉"进来

有些设备装不了 Tailscale——比如老式打印机、监控摄像头、或者一整段内网。这时用子网路由(Subnet Router):找一台同时能进这个内网、又能接入 tailnet 的机器(比如家里的软路由或 NAS),让它替整个网段"代言"。

在这台机器上声明要转发的网段:

`bash sudo tailscale up --login-server https://hs.example.com --authkey <密钥> \ --advertise-routes=192.168.0.0/24,10.0.0.0/8 `

如果它已经注册过,就用 tailscale set 补声明:

`bash sudo tailscale set --advertise-routes=192.168.0.0/24 `

注意子网路由是双重确认(double opt-in):客户端声明只是第一步,还必须在控制服务器上审批。先看有哪些待审批的路由,再批准:

`bash sudo headscale nodes list-routes sudo headscale nodes approve-routes --identifier 1 --routes 192.168.0.0/24 `

最后,在需要使用这些网段的机器上接受路由:

`bash sudo tailscale set --accept-routes `

同时别忘了在子网路由那台机器上开启系统 IP 转发,否则流量进得来出不去。

第九步:Exit Node,让流量从指定节点出去

出口节点(Exit Node)用于把某台机器的全部上网流量,经 tailnet 从另一台节点出去。典型场景:在不受信任的公共 Wi-Fi 上,让手机流量从家里的机器出去;或让云端机器用某个固定出口 IP 访问第三方服务。

在准备当出口的节点上声明:

`bash sudo tailscale up --login-server https://hs.example.com --authkey <密钥> --advertise-exit-node `

到控制服务器上审批(出口节点会广播 0.0.0.0/0 和 ::/0,二者批其一即可,另一个会自动通过):

`bash sudo headscale nodes list-routes sudo headscale nodes approve-routes --identifier 1 --routes 0.0.0.0/0 `

然后在使用方机器上挂上这个出口:

`bash sudo tailscale set --exit-node myexit `

同样,出口节点所在机器也要开启 IP 转发。

第十步:用 ACL 策略管住"谁能访问谁"

默认情况下,同一个 tailnet 里的节点互相全通。这在个人使用时没问题,但在团队或混合场景下必须收紧。Headscale 支持 Tailscale 的 ACL / Grants 策略,通过 policy.mode: file 指定一个 HuJSON 策略文件,例如 /etc/headscale/policy.json:

`json { "hosts": { "router": "100.64.0.1/32", "node": "100.64.0.2/32", "service.example.net": "192.168.0.1/32" }, "grants": [ { "src": ["node"], "dst": ["service.example.net"], "ip": ["80,443"] } ] } `

这段策略的含义是:允许 node 访问 service.example.net 的 80/443 端口,而不能直接访问子网路由本身。策略的语法与 Tailscale 官方一致(官方文档有完整的 ACL/Grants 参考),初次接触建议先用小网络试跑,避免误锁自己在外面。

第十一步:备份与升级

备份极其简单——Headscale 用 SQLite,全部状态就是 /var/lib/headscale/ 这一个目录(含数据库、Noise 私钥、DERP 私钥、证书缓存)。定期打包异地存放即可:

`bash sudo tar czf /root/headscale-backup-$(date +%F).tar.gz /var/lib/headscale `

⚠️ 这个目录里含私钥,备份文件务必加密或严格限权,不要丢到公开网盘。

升级前先看官方 release notes(Headscale 迭代较快,偶有配置项调整),然后替换二进制并重启:

`bash wget --output-document=headscale-new.deb \ "https://github.com/juanfont/headscale/releases/download/v最新版本/headscale_最新版本_linux_amd64.deb" sudo apt install ./headscale-new.deb sudo systemctl restart headscale sudo headscale nodes list `

四、安全加固清单

Headscale 的暴露面本来就很小(只开 443),但下面这几条依然值得逐项落实:

1. 只开放必要端口:对外只留 TCP 443;内置 DERP 才需要 UDP 3478。SSH 建议改端口 + 仅密钥登录,或干脆放进 tailnet 里只走内网访问。 2. trusted_proxies 留空或严格限定:官方警告,若在没有反代的情况下设置它,客户端就能伪造自己的来源 IP,污染日志与策略。只有当确实有反代时才填反代的 CIDR。 3. 反代并非官方首选:Headscale 官方在 README 里明确写了"我们不支持也不鼓励用反代和容器来运行 Headscale"。虽然社区文档给出了 Nginx 反代方案,但如果要这么做,必须注意两个协议细节——Tailscale 控制协议用 POST 方法升级 WebSocket,且 Upgrade 头的值是 tailscale-control-protocol(不是常规的 websocket)。反代配置错一个头,客户端就会一直连不上。 4. 及时轮换密钥:预授权密钥默认 1 小时、单次有效,别图省事生成永久可复用的密钥。节点不再需要时用 headscale nodes expire 主动过期。 5. 定期备份 /var/lib/headscale/,尤其是里面的 Noise 私钥——丢了它,所有节点都需要重新注册。 6. 给 Headscale 配一个独立域名子域,不要把控制服务器和你的博客/业务混在同一个域名下,隔离风险也让排查更清晰。

五、常见问题 FAQ

Q1:Headscale 和 Tailscale 是什么关系?我能完全脱离官方账号吗? Headscale 是 Tailscale 控制服务器的开源复刻,两者底层都用 WireGuard 传数据、都支持 Tailscale 官方客户端。区别在于:Tailscale 官方的控制服务器是闭源 SaaS,需要注册账号;Headscale 由你自己部署,账号、数据库、密钥全在你手里,客户端把 --login-server 指向你的地址即可,完全可以不用注册官方账号。注意 Headscale 官方声明它"与 Tailscale Inc. 没有关联",它只实现单个 tailnet,定位是个人 / 小团队 / 自建爱好者。

Q2:节点之间的流量会经过我的服务器吗?会不会吃掉大量流量? 绝大多数情况下不会。节点之间会先尝试 NAT 穿透建立点对点直连,数据直接从 A 到 B,不绕经 Headscale。Headscale 只做协调(换公钥、分地址、下发策略),本身几乎不吃带宽。只有两端都无法直连时,流量才会回落到中继(DERP)——此时若你用的是官方免费 DERP 地图,走的是 Tailscale 的中继节点;若你自建了内置 DERP,才走你自己的机器。这也是它比 frp 中转省流量的根本原因。

Q3:一定要用域名吗?能不能直接用 IP? 强烈建议用域名。客户端在某些场景下硬编码假定 HTTPS 的 443 端口且依赖有效证书,裸 IP + 自签证书会带来一堆信任问题;内置 Let's Encrypt 也要求域名。所以给自己配一个子域名(如 hs.example.com),并确保它解析到服务器真实 IP(不能走 CDN 代理)。

Q4:客户端执行 tailscale up 后一直转圈 / 连不上,怎么办? 按这个顺序排查:① curl https://hs.example.com/health 控制服务器是否健康;② server_url 是否与证书域名完全一致;③ DNS 的 A 记录是否指向真实 IP、有没有被 CDN 代理;④ 443 端口是否放行;⑤ journalctl -u headscale 里有没有证书申请失败。用 Nginx 反代时,还要确认 Upgrade 头是 tailscale-control-protocol、且允许 POST 升级 WebSocket。

Q5:国内网络环境能用吗?速度如何? 控制服务器能访问、且客户端能连通 443 即可用。速度取决于两台节点之间的直连质量,与 Headscale 服务器位置关系不大——因为它只做协调,不走数据。如果 NAT 穿透失败会走 DERP 中继,中继节点离你越近速度越好,所以有条件时可以把 Headscale 部署在离你常用的节点较近的区域,并自建内置 DERP 提升中继质量。选择海外云服务器时,优先挑面向中国大陆线路较优的区域(如香港、日本、新加坡)。

Q6:支持哪些客户端操作系统? Tailscale 官方客户端覆盖主流平台:Linux、Windows、macOS、iOS、Android,以及 BSD、部分 NAS 系统(群晖等)。只要客户端支持自定义登录服务器(--login-server / 在 App 里选择"替代服务器"),就能接入 Headscale。

Q7:1 核 1G 的机器能带多少节点? Headscale 的资源开销主要来自 SQLite 和少量内存,个人或小团队几十个节点毫无压力,1 核 1G 足够。真正吃资源的是你是否自建 DERP、是否同时把它当 Exit Node——那才是带宽和流量的消耗点。

Q8:headscale nodes list 里节点显示 offline,是坏了吗? 通常是客户端那侧的问题:机器休眠、Tailscale 服务没启动、或者本地网络被限制出站。先在客户端上 tailscale status 看它在尝试连哪个控制服务器,再对一下控制服务器日志。注意节点 key 默认不会过期(node.expiry: 0),但如果配置了有效期,过期后节点会转 offline,需要重新登录。

Q9:DERP 是什么?我需不需要自建? DERP 是"直连失败时的加密中继"。先不要自建——官方免费 DERP 地图开箱即用,配置里 derp.server.enabled 保持 false 即可。等你发现频繁走中继、速度不理想时,再按官方文档启用内置 DERP(改 enabled: true,填公网 IP,放行 UDP 3478)。注意:如果为了"纯净"把官方 DERP 地图去掉(urls: []),你的自建 DERP 就成了唯一中继,一旦它挂了连通性会受影响——这是一个单点,要权衡。

Q10:能不能把整个家庭局域网都接进来? 可以,用子网路由。找一台能进该局域网、又能接入 tailnet 的机器 --advertise-routes=192.168.0.0/24,然后在控制服务器 headscale nodes approve-routes 审批,其他节点 tailscale set --accept-routes 接受即可。记得在子网路由机器上开启 IP 转发。

Q11:我的服务器是 CentOS 7,能装吗? Headscale 是静态链接的 Go 二进制,官方提供 .deb 包和裸二进制,运行时并不依赖高版本 glibc,所以 CentOS 7 的 glibc 2.17 不是障碍(用裸二进制方式安装即可)。但 CentOS 7 已 EOL、安全更新停滞,本文仍建议新机器直接上 Ubuntu 22.04/24.04 或 Debian 12,省去兼容与安全上的心智负担。

Q12:数据存在哪里?怎么备份? 全部状态都在 /var/lib/headscale/:SQLite 数据库 db.sqlite、Noise 私钥 noise_private.key、可选的 DERP 私钥、Let's Encrypt 证书缓存。把这个目录打包异地存放即可完成备份。注意其中含私钥,备份文件要加密并限权。恢复时把目录还原回去再重启服务即可。

Q13:官方说 Postgres 是用 SQLite 之外的另一个选项,我该用哪个? 用 SQLite。 官方配置注释里写明:Postgres "仅为历史遗留而支持",所有新开发、测试和优化都围绕 SQLite 进行。除非你有非常特殊的理由,否则不要自找麻烦。

Q14:怎样踢掉一台不再使用的设备? 先列出节点找到它的 ID,然后主动使其过期:sudo headscale nodes expire --identifier <ID>。之后该节点需重新登录才能接入。建议配合定期清理预授权密钥(headscale preauthkeys list / expire)一起做。

Q15:Headscale、frp、WireGuard,我到底该选哪个? 看你的真实需求:想"把内网某个服务发布到公网给外部人访问"——选 frp;"没有公网 IP、一个入站端口都不想开,只想出站发布"——选 Cloudflare Tunnel;"我只需要两台机器之间一条稳的加密隧道,且我清楚它们的端点"——选 WireGuard;"我有一堆机器散落各地,想让它们零配置互相发现、互相直连、还要统一身份和访问控制"——那正是 Headscale 的用武之地。它们并不互斥,完全可以组合使用。

六、总结

回到最初的问题:当你的机器散落在不同的云、不同的家庭网络、不同的 NAT 之后,真正缺的从来不是"又一条隧道",而是一个组网层。Headscale 用一台最便宜的海外云服务器,就把这个组网层补上了——它自动帮你交换密钥、分配地址、穿透 NAT、下发路由与策略,让每台机器只需接入一次,就能用 主机名.vpn.example.com 互相访问。

它的优点是清晰而实在的:开源可控、暴露面极小(通常只开 443)、几乎不吃资源、备份就是打包一个目录、客户端全平台覆盖。代价同样要诚实面对:控制服务器是单点,需要你认真备份;NAT 穿透不是 100% 成功,必要时得接受 DERP 中继;以及——它需要你动手,而不是点几下后台。

如果你正准备给自己的多台服务器、家里的 NAS、以及随身设备搭一张随时可用的私有内网,Headscale 是当下自建方案里性价比最高的一张门票。选一台合适的海外云服务器,跟着本文十一步走一遍,你会发现:把散落各地的机器连成一张网,原来可以这么省心。

> 本文由 5.chengzicloud.cloud 提供,点击访问首页了解更多海外云服务器部署方案和专属优惠。

延伸阅读:

- 海外云服务器搭建 WireGuard 轻量 VPN 完整教程 - 海外云服务器搭建 frp 内网穿透完整教程 - Cloudflare Tunnel 免公网 IP 内网穿透部署指南 - Nginx 反向代理 + Let's Encrypt SSL 证书完整配置教程 - 海外云服务器备份与灾难恢复实战指南 - 海外云服务器安全加固完整指南