自建 Headscale 服务器部署 Wiki

基于 Headscale 0.28.0 + Caddy + Tailscale,使用自定义域名搭建私有 Tailscale 控制服务器。


一、架构设计

客户端 (Tailscale)
    │
    │  HTTPS (443)
    ▼
Caddy 反向代理
  example.com / www.example.com
  自动申请 TLS 证书 (Let's Encrypt)
    │
    │  HTTP (8081, 本地)
    ▼
Headscale 控制服务器
  监听 0.0.0.0:8081
  SQLite 数据库
    │
    │  DERP 中继(使用 Tailscale 官方节点)
    ▼
各节点之间 P2P 或中继通信

组件职责:

组件 职责
Caddy 反向代理 + 自动 HTTPS 证书
Headscale 开源 Tailscale 控制服务器,管理节点注册、密钥、ACL
Tailscale 客户端 各设备上的 headscale客户端,连接到自建控制服务器
DERP 中继服务器,P2P 打洞失败时使用(此处复用 Tailscale 官方节点)

二、前置条件

  • Ubuntu 22.04 / 24.04 服务器,有公网 IP
  • 域名已将 A 记录指向服务器公网 IP(本例:example.comwww.example.com
  • 服务器开放端口:80(HTTP 验证)、443(HTTPS)

三、安装 Caddy

# 安装 Caddy(官方源)
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
  | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
  | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy

配置 Caddyfile

sudo vim /etc/caddy/Caddyfile

写入以下内容:

example.com, www.example.com {
    reverse_proxy localhost:8081 {
        header_up Host {http.request.host}
        header_up X-Forwarded-Host {http.request.host}
        header_up X-Forwarded-Proto {http.request.proto}
        header_up X-Forwarded-For {http.request.remote.host}
    }

    encode gzip zstd

    header {
        Strict-Transport-Security "max-age=31536000;"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
    }
}
# 格式化并验证配置
sudo caddy fmt --overwrite /etc/caddy/Caddyfile

# 重载 Caddy
sudo systemctl reload caddy

四、安装 Headscale

国内访问 GitHub 可能受限,使用镜像站下载。

# 下载 0.28.0 deb 包(使用 kkgithub 镜像)
wget -O headscale_0.28.0.deb \
  "https://kkgithub.com/juanfont/headscale/releases/download/v0.28.0/headscale_0.28.0_linux_amd64.deb"

# 安装
sudo apt install -f ./headscale_0.28.0.deb

# 启动并设置开机自启
sudo systemctl enable --now headscale

五、配置 Headscale

sudo vim /etc/headscale/config.yaml

完整配置如下:

---
server_url: https://www.example.com

listen_addr: 0.0.0.0:8081
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443

private_key_path: /var/lib/headscale/private.key

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

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

database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite

policy:
  mode: disabled

dns:
  magic_dns: true
  base_domain: headscale.internal
  override_local_dns: true
  nameservers:
    global:
      - 223.5.5.5
      - 223.6.6.6

derp:
  server:
    enabled: false
  urls:
    - https://controlplane.tailscale.com/derpmap/default
  auto_update_enabled: true

log:
  level: info

unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"
# 重启服务
sudo systemctl restart headscale
sudo systemctl status headscale

六、创建用户并添加节点

创建用户

sudo headscale users create myfamily

# 查看用户列表(含 ID)
sudo headscale users list

生成 Pre-Auth Key(推荐方式)

# 生成可复用的 authkey,有效期 24 小时
sudo headscale preauthkeys create --user myfamily --reusable --expiration 24h

输出示例:

hskey-auth-xNBe_HAAxdKh-rH4mMfD58A7CXZbrExrxzUKAvlc-fJioNS25S9caoKp5bqZMNlhAgBL1l-TREBdn

客户端接入

Windows / macOS / Linux:

tailscale up --login-server=https://www.example.com --authkey=<上面生成的key>

Android / iOS: 参考 官方文档,在客户端设置中填写自定义控制服务器地址后使用 authkey 登录。

查看已注册节点

sudo headscale nodes list

七、常见坑及处理措施

坑 1:ip_prefixes 字段不被识别

报错: no IPv4 or IPv6 prefix configured, minimum one prefix is required

原因: Headscale 0.23+ 将字段从 ip_prefixes 改为 prefixes,格式也发生变化。

处理: 使用新格式:

# ❌ 旧版写法
ip_prefixes:
  - 100.64.0.0/10

# ✅ 新版写法
prefixes:
  v4: 100.64.0.0/10
  v6: fd7a:115c:a1e0::/48

坑 2:server_urlbase_domain 冲突

报错: server_url cannot be part of base_domain in a way that could make the DERP and headscale server unreachable

原因: Headscale 会检测 server_url 的域名是否属于 base_domain 的子域(或同域)。如果是,Magic DNS 会劫持控制服务器域名,导致客户端断连。

例如 server_urlwww.example.combase_domainexample.comts.example.com 都会触发此问题(父子域关系)。

处理: base_domain 使用与 server_url 完全无关的域名:

dns:
  base_domain: headscale.internal  # ✅ 完全隔离,不需要真实注册

坑 3:数据库字段改名

报错: invalid database type "", must be sqlite, sqlite3 or postgres

原因: 新版将顶层 db_type / db_path 改为嵌套结构。

处理:

# ❌ 旧版写法
db_type: sqlite3
db_path: /var/lib/headscale/db.sqlite

# ✅ 新版写法
database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite

坑 4:旧数据库 Schema 不兼容

报错: SQLite schema failed to validate: Remove table "machines" ...

原因: 旧版本遗留的数据库表结构与新版不兼容,无法自动迁移。

处理: 若无重要数据,删除数据库文件让 Headscale 重建:

sudo systemctl stop headscale
sudo rm /var/lib/headscale/db.sqlite
sudo systemctl start headscale

⚠️ 若有已注册节点需保留,应先降级到原版本导出数据,或查阅对应版本的迁移文档。


坑 5:--user 参数接受 ID 而非用户名

报错: invalid argument "myfamily" for "-u, --user" flag: strconv.ParseUint: parsing "myfamily": invalid syntax

原因: 部分版本的 preauthkeys create 命令 --user 参数只接受数字 ID。

处理:

# 先查询用户 ID
sudo headscale users list

# 使用 ID
sudo headscale preauthkeys create --user 1 --reusable --expiration 24h

坑 6:将节点 key 当 authkey 使用

报错: auth-key not found

原因: tailscale up 交互式登录产生的 nodekey:xxx 是节点密钥,需要在服务端用 headscale nodes register 来注册;而 --authkey 参数需要的是通过 headscale preauthkeys create 生成的 hskey-auth-xxx

处理: 两种接入方式二选一:

# 方式一:服务端生成 authkey,客户端直接使用(推荐)
sudo headscale preauthkeys create --user myfamily --reusable --expiration 24h
tailscale up --login-server=https://www.example.com --authkey=hskey-auth-xxx

# 方式二:客户端生成 nodekey,服务端手动注册
tailscale up --login-server=https://www.example.com   # 复制输出的 nodekey
sudo headscale nodes register --key nodekey:xxx --user myfamily

八、日常运维命令

# 查看服务状态
sudo systemctl status headscale

# 查看实时日志
sudo journalctl -u headscale.service -f

# 用户管理
sudo headscale users list
sudo headscale users create <name>

# 节点管理
sudo headscale nodes list
sudo headscale nodes delete --identifier <id>

# Pre-Auth Key 管理
sudo headscale preauthkeys list --user myfamily
sudo headscale preauthkeys expire --user myfamily --key <key>

# Caddy 配置重载
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo systemctl reload caddy

九、参考资料

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐