第一章:架构与环境准备 (Infrastructure & Preparation)
1.1、安装 Docker Engine (官方推荐方式)
不要使用 apt install docker.io,为了 2026 年的兼容性,我们直接上 Docker 官方源。
# 1. 更新系统索引并安装基础依赖
apt-get update && apt-get install -y curl vim git
# 2. 使用官方一键安装脚本 (这是 2026 年最稳健的姿势)
curl -fsSL https://get.docker.com | sh
# 3. 检查 Docker 状态
# 预期输出应包含 Docker version 2x.x.x 以及 Docker Compose version v2.x.x
docker --version && docker compose version
1.2、开启内核 IP 转发
这是组网的“灵魂”,必须永久生效。
# 临时开启
sudo sysctl -w net.ipv4.ip_forward=1
# 永久开启
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
1.3、部署流量闸门 (Nginx Proxy Manager)
我们先建立一个专门的目录来存放所有的组网容器配置。
1.3.1、建立工作目录
mkdir -p /root/iot-architect/network
cd /root/iot-architect/network
mkdir -p ~/iot-architect/network/headscale/config
mkdir -p ~/iot-architect/network/headscale/data
mkdir -p ~/iot-architect/network/npm/data
mkdir -p ~/iot-architect/network/npm/letsencrypt
1.3.2、编写 docker-compose.yml
我们将 NPM 放在这里,它是所有流量的入口。
cat <<'EOF' > ~/iot-architect/network/docker-compose.yml
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: npm
restart: unless-stopped
ports:
- '80:80'
- '81:81' # 管理后台端口
- '443:443'
volumes:
- ./npm/data:/data
- ./npm/letsencrypt:/etc/letsencrypt
networks:
- headscale-net
networks:
headscale-net:
name: headscale-net
EOF
1.3.3、启动服务
docker compose up -d
1.3.4、 基础环境对齐检查 (Verification)
在继续之前,请确认以下状态:
- 访问管理后台: 在浏览器打开
http://你的服务器IP:81。- 默认账号:
admin@your-domain.com - 默认密码:
password
- 默认账号:
- 准备域名: 既然你有
,我建议为主线教程预留三个子域名:your-domain.comhs.(用于 Headscale 控制面)your-domain.comhs-ui.(用于 Headscale Web控制)your-domain.comderp.(用于 DERP 中继节点)your-domain.com
第二章:核心控制面——Headscale 容器化部署
2.1、部署 Headscale 核心服务
Headscale 是整个组网的“大脑”,它负责分发密钥和管理节点。
2.1.1、准备配置目录
在 /root/iot-architect/network 目录下创建 headscale 专属配置空间:
mkdir -p ./headscale/config
# 创建一个空的数据库文件,防止容器启动时因权限或文件缺失报错
touch ./headscale/data/db.sqlite
2.2.2、初始化 config.yaml
在 ./headscale/config/ 目录下创建 config.yaml。
脱敏提示: 教程中请将
your-domain.com替换为您实际在 Cloudflare 解析好的域名(如hs.)。your-domain.com
cat <<'EOF' > ~/iot-architect/network/headscale/config/config.yaml
# --- Headscale 2026 核心配置文件 (全栈兼容生产版) ---
# [基础设置]
# 客户端连接的外部地址。虽然容器内监听 8080,但外部通过 NPM 反代 443 接入。
server_url: https://hs.your-domain.com
# 服务监听地址。使用 "[::]" 可同时绑定 IPv4 和 IPv6 所有的物理网卡。
listen_addr: "[::]:8080"
# 指标监控与调试地址。用于 Prometheus 监控容器运行状态。
metrics_listen_addr: "[::]:9090"
# gRPC 监听地址。用于 Headscale 远程管理,必须配合证书使用。
grpc_listen_addr: "[::]:50443"
grpc_allow_insecure: false
# [安全协议]
# 噪声协议 (TS2021) 密钥路径,容器启动时会自动生成密钥文件。
noise:
private_key_path: /var/lib/headscale/noise_private.key
# [内网 IP 分配]
# 必须使用 Tailscale 官方定义的子集网段,确保客户端逻辑兼容。
prefixes:
v4: 100.64.0.0/10 # IPv4 CGNAT 保留网段
v6: fd7a:115c:a1e0::/48 # IPv6 ULA 私有地址网段
allocation: sequential # IP 分配策略:顺序分配
# [中继服务器 (DERP) 配置]
derp:
server:
enabled: false # 初次部署建议关闭,待主线连通后再开启自建 DERP 专章
region_id: 999
region_code: "headscale"
region_name: "Headscale Embedded DERP"
stun_listen_addr: "[::]:3478"
private_key_path: /var/lib/headscale/derp_server_private.key
automatically_add_embedded_derp_region: true
# 外部 DERP 列表。默认拉取官方节点,保证基础连通性。
urls:
- https://controlplane.tailscale.com/derpmap/default
auto_update_enabled: true
update_frequency: 3h
# [数据库配置]
# 2026 年官方建议生产环境统一使用 SQLite,性能稳健且易于备份。
database:
type: sqlite
debug: false
sqlite:
path: /var/lib/headscale/db.sqlite
write_ahead_log: true # 开启 WAL 模式,提升多端接入时的并发写入能力
# [核心 DNS 配置]
# 注意:global 采用 JSON 数组格式 ["IP1", "IP2"],这是解决 v0.28.0 解析 Bug 的关键。
dns:
magic_dns: true # 开启内部主机名解析,允许通过机器名互访
base_domain: your-domain.com # 内网私有后缀
override_local_dns: true # 强制客户端使用 Headscale 下发的 DNS 设置
nameservers:
global: ["223.5.5.5", "2400:3200::1", "119.29.29.29", "2402:4e00::", "1.1.1.1", "2606:4700:4700::1111"]
split: {}
search_domains: []
extra_records: []
# [日志与安全]
log:
level: info
format: text
# 权限策略。暂不启用外部 ACL 文件,后续可在 UI 面板中细化。
policy:
mode: file
path: ""
# 文件分享功能 (Taildrop)。允许组网内的设备直接互传文件。
taildrop:
enabled: true
# 本地通信套接字。用于宿主机 docker exec 命令免密管理容器。
unix_socket: /var/run/headscale/headscale.sock
unix_socket_permission: "0770"
# [其他杂项]
disable_check_updates: false
ephemeral_node_inactivity_timeout: 30m
randomize_client_port: false
EOF
2.2.3、更新 docker-compose.yml
将 Headscale 服务加入到我们的网络架构中。编辑之前的 docker-compose.yml:
cat <<'EOF' > ~/iot-architect/network/docker-compose.yml
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: npm
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./npm/data:/data
- ./npm/letsencrypt:/etc/letsencrypt
networks:
- headscale-net
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
volumes:
- ./headscale/config:/etc/headscale
- ./headscale/data:/var/lib/headscale
# 我们不需要直接映射端口到宿主机,因为流量会通过 NPM 进入
command: serve
networks:
- headscale-net
networks:
headscale-net:
name: headscale-net
EOF
2.2.4、启动并联调
执行以下命令启动服务:
docker compose up -d
2.2.5、NPM 反向代理配置
启动容器后,你需要进入 NPM 的管理后台(http://IP:81),按照以下步骤操作:
- Add Proxy Host:
- Domain Names:
hs.(你的域名)your-domain.com - Scheme:
http - Forward Name/IP:
headscale(这里直接填容器名,因为在同一网络下) - Forward Port:
8080
- Domain Names:
- SSL 标签页:
- 选择 Request a new SSL Certificate。
- 开启 Force SSL。
- 同意协议并保存。
- Advanced 标签页:
# 允许跨域请求的配置
location / {
# 允许来自 UI 域名的请求
add_header 'Access-Control-Allow-Origin' 'https://hs-ui.your-domain.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
# 处理浏览器的预检请求 (OPTIONS)
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://hs-ui.your-domain.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
# 转发请求给后端 Headscale 容器
proxy_pass http://headscale:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 兼容 Tailscale 的 Websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}2.2.6、既然“大脑”已经开始稳定呼吸,我们要正式激活管理权限。请依次执行:
- 创建命名空间:
docker exec -it headscale headscale namespaces create default - 生成 UI 面板钥匙 (API Key):
docker exec -it headscale headscale apikeys create --expiration 90d
一旦拿到 API Key,我们将配置 Nginx Proxy Manager (NPM) 并上线可视化管理面板,彻底结束命令行时代!
第三章:可视化管理——Headscale-UI 的集成
3.1、部署 Headscale-UI
接下来,我们将可视化管理面板加入到 docker-compose.yml 中。请修改文件,在 services 下追加:
headscale-ui:
image: ghcr.io/gurucomputing/headscale-ui:latest
container_name: headscale-ui
restart: unless-stopped
networks:
- headscale-net修改完成后,执行部署:
docker compose up -d现在我们进入最后的“合体”阶段:通过 Nginx Proxy Manager (NPM) 将服务安全地发布到公网,并在浏览器中激活可视化管理。
3.2、Nginx Proxy Manager (NPM) 配置对齐
请登录您的 NPM 管理后台 (http://IP:81),添加以下两个 Proxy Host。由于所有容器都在 headscale-net 网络中,我们直接用容器名转发,这最安全也最专业。
3.2.1、 配置 Headscale-UI 转发
- Domain Names:
hs-ui.your-domain.com - Scheme:
http - Forward Name:
headscale-ui - Forward Port:
8080 - SSL 选项: 同样开启 Force SSL。
3.2.2、UI 面板激活
访问 https://hs-ui.your-domain.com,您会看到一个设置页面。请填入以下信息进行“握手”:
- Headscale URL:
https://hs.your-domain.com(必须带 https) - API Key:
hskey-api-yvZkXQYOAmoq-F4XXCvA7h2YQaHP3l8senWI1aXxcBW_W_UKsC2KYfsZ_-a86Z6bOHigGbOKFxwVZ
点击 Save。如果配置正确,您将看到左侧侧边栏显示出 default 命名空间,此时您的可视化“指挥部”正式上线。
第四章:性能飞跃——自建 DERP 中继节点
- 核心痛点: 解决国内运营商对原生 Tailscale 节点的 UDP 封锁。
- Docker 方案: 部署
derper容器,配置证书自动映射。 - 验证环节: 使用
tailscale netcheck测试中继延迟。
第五章:多端接入与子网路由 (Subnet Router)
- 全平台接入: Linux (Docker/Native)、Windows、iOS/Android 接入技巧。
- 打通局域网: 开启
advertise-routes,让远程设备透明访问内网 NAS 或 PLC。 - 出口节点: 开启
exit-node实现异地安全上网。
第六章:运维监控与自动化
- 健康检查: Uptime Kuma 监控服务状态。
- 版本管理: Watchtower 自动更新容器。
- 备份方案: 定期备份
db.sqlite数据库。

