跳到主要内容

部署私有的 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 加入网络 #

  1. 在 headscale-ui 上创建 Pre-AuthKey,注意,默认 Key 只能用一次,如果想让 key 多次使用,需要勾选 reusable 选项
  2. 参考 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可控,官方的随机生成。

参考资料 #