部署私有的 Headscale 控制台
目录
使用 Tailscale 有一段时间了,体验上除了性能比原生的 Wireguard 差一些,整体上来说使用体验十分不错,打算更进一步部署自己的 Headscale 节点来取代官方的 admin 管理控制台,毕竟全开源还是比半开源来得更纯粹。
日常工作里,经常有一些内网访问的需求,tailscale 的整体体验很不错,可惜除了控制台以外其他都开源,想着不如纯粹一点,将控制台也替换成开源的,这样用起来会更加方便,本文记录了一下使用 headscale 和 headscale-ui 搭建了一个私有控制台:
使用 Docker Compose 部署 headscale #
headscale 是不带 UI 界面的,用起来多少有些不方便,headscale-ui 可以很好的填补这个空白,一般而言,headscale 和 headscale-ui 是共用一个域名的,headscale-ui 作为一个 path 访问,类似这样:https://example.domain/web
mkdir -p /opt/headscale
mkdir -p /opt/headscale/config
mkdir -p /opt/headscale/data
cd /opt/headscale
nano docker-compose.yml
下面是 docker-compose.yml
部署文件
version: '3'
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
command: headscale serve
restart: unless-stopped
volumes:
- /opt/headscale/config:/etc/headscale/
- /opt/headscale/data:/var/lib/headscale/
ports:
- "8080:8080"
headscale-ui:
image: ghcr.io/gurucomputing/headscale-ui:latest
restart: unless-stopped
container_name: headscale-ui
ports:
- "8090:80"
headscale 配置文件 #
headscale 提供一个 example 配置文件,我们需要做的是获取到这个 example 配置,并在这个基础上进行修改,具体每个配置的作用已经在文件里说明的很清楚了。
wget -O ./config/config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml
我修改了下面提到几个项,你可以根据自己的情况进行实际调整
```yaml
server_url: https://hs.yourdomain.com # FQDN, 指定访问的 domain
listen_addr: 0.0.0.0:8080 # 监听 8080 端口
ip_prefixes: # 调整 IP 显示,先显示 IPv4,而后IPv6
- 100.64.0.0/10
- fd7a:115c:a1e0::/48
disable_check_updates: true # 不检查 headscale 的新版本
dns_config:
override_local_dns: false # 不要覆盖本地 DNS 服务
randomize_client_port: true # 使用随机端口
Nginx 反向代理配置 #
这里我们需要同时给 headscale 和 headscale-ui 做反向代理配置,这里是我的反向代理配置(SSL证书还请自行申请)
server {
server_name hs.yourdomain.com;
# Security / XSS Mitigation Headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
location /web {
proxy_redirect off;
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_pass http://127.0.0.1:8090;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_redirect http:// https://;
proxy_buffering off;
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 $http_x_forwarded_proto;
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
}
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/hs.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/hs.yourdomain.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = hs.yourdomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name hs.yourdomain.com;
return 404;
}
初始化 headscale 和 headscale-ui #
headscale 和 headscale-ui 之间的通讯是通过 API 进行的,因此我们需要给 headscale 申请一个有效的 APIKey,命令如下:
docker compose exec headscale headscale apikeys create -e 720d
其中,参数 720d 是指我们需要创建一个有效期为 720 天的 APIKey,请妥善保存生成的APIKey
创建一个用户
docker compose exec headscale headscale namespaces create main
上面的命令创建了一个 main 用户,并为 main 用户创建了一个实效为 24 小时的 preauth-key 最后,进入你的 headsclale-ui 的页面,填入正确的 APIKey 和 hostname,私有的控制台就部署成功了
使用 tailscale 加入网络 #
- 在 headscale-ui 上创建 Pre-AuthKey,注意,默认 Key 只能用一次,如果想让 key 多次使用,需要勾选 reusable 选项
- 参考 tailscale官方安装文档,但启动命令修改为如下:
tailscale up --accept-routes=true --accept-dns=false --login-server=https://hs.yourdomain.com --auth-key=[YOUR-PRE-AUTHKEY]
FAQ #
Q:是否有必要自建 DERP 节点? A:DERP 节点是用作“打洞”的,自建的 headscale 已经附带了 tailscale 官方的 DERP 节点,如有额外需要可以自建
Q:访问 headscale-ui 不需要用户名和密码,是否不安全? A:headscale-ui 上的 APIKEY 和 hostname 都是存储在浏览器的 local-storage 里,只要你的 APIKey 没有泄露,理论上就是安全的。实在不放心可以考虑使用 Cloudflare Zero Trust 机制来保护你的 headscale-ui
Q:和使用 tailscale 官方面板比较,这个有什么不同? A:基本功能的区别其实不大,甚至官方面板能提供的功能更多,大约有那么一个好处就是这个生成的内网IP可控,官方的随机生成。