部署前提:

  • 有自己的域名,解析到服务器中

例如

headscale.nekotech.xyz

derp.nekotech.xyz

  • 已安装好Docker

创建docker网络

docker network create headscale-network

创建好项目相关目录

mkdir -p /opt/headscale
mkdir -p /opt/headscale/container-config
mkdir -p /opt/headscale/container-data

cd /opt/headscale

下载配置文件到配置目录

wget https://github.com/juanfont/headscale/raw/main/config-example.yaml -O /opt/headscale/container-config/config.yaml

修改配置文件,将所有127.0.0.1部分替换成0.0.0.0

sed -i 's/127.0.0.1/0.0.0.0/g' /home/docker/headscale/config/config.yaml

继续修改配置以下内容,其余默认

server_url: https://headscale.nekotech.xyz #这部分http://0.0.0.0:8080按实际修改成自己域名

prefixes: #将v4部分放到前面,网段可按实际修改
  v4: 100.64.0.0/10
  v6: fd7a:115c:a1e0::/48

randomize_client_port: true #客户端随机端口,按实际修改

再添加derp配置

cat << EOF > /opt/headscale/container-config/derp.yaml
regions:
  900:
    regionid: 900
    regioncode: ali
    regionname: Aliyun HangZhou
    nodes:
      - name: 900a
        regionid: 900
        hostname: derp.nekotech.xyz
        # ipv4: ip
        stunport: 3478
        stunonly: false
        derpport: 443
EOF

编辑docker-compose.yml文件

services:
  headscale:
    container_name: headscale
    image: headscale/headscale:v0.23.0-alpha11
    restart: unless-stopped
    expose:
      - "8080"
      - "9090"
    volumes:
      - ./container-config:/etc/headscale
      - ./container-data:/var/lib/headscale
    entrypoint: headscale serve
    networks:
      headscale-network:

  derper:
    container_name: derper
    image: fredliang/derper
    restart: always
    ports:
      - 3478:3478/udp
      # - 19850:19850  # 如果没有启用自定义的 network,则19850需要暴露出去
    environment:
      - DERP_DOMAIN=derp.nekotech.xyz
      - DERP_CERT_MODE=letsencrypt
      - DERP_ADDR=:19850
      - DERP_VERIFY_CLIENTS=false
    volumes:
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
    networks:
      headscale-network:


networks:
  headscale-network:
    external: true

启动项目容器

docker compose up -d

服务器需要开放的端口

DREP服务

UDP 3478 端口 UDP 41641 端口

NPM服务

TCP 80 443 81 端口

通过NPM反代,容器安装NPM和MYSQL

version: "3"

services:
  mysql:
    image: mysql:8.1.0
    container_name: npm_db
    restart: on-failure:3
    command:
      - --default-authentication-plugin=caching_sha2_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=truei
    expose:
      - "3306"
        # ports:
        # - "1307:3306"
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    deploy:
      resources:
        limits:
          memory: 512M
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
      - MYSQL_ROOT_PASSWORD=npm@Password
      - MYSQL_DATABASE=npm
      - TZ=Asia/Shanghai
    networks:
      headscale-network:

  npm:
    image: jc21/nginx-proxy-manager:latest
    container_name: npm
    restart: unless-stopped
    environment:
      TZ: Asia/Shanghai
      DB_MYSQL_HOST: mysql
      DB_MYSQL_PORT: 3306
      DB_MYSQL_USER: "root"
      DB_MYSQL_PASSWORD: "npm@Password"
      DB_MYSQL_NAME: "npm"
    ports:
      - '80:80'  # Public HTTP Port
      - '443:443'  # Public HTTPS Port
      - '838:81' # Admin Web Port
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    deploy:
      resources:
        limits:
          memory: 256M
    networks:
      headscale-network:

networks:
  headscale-network:
    external: true

添加npm反代headscale配置,SSL证书选自动申请

再添加derp服务的反代设置,SSL证书同样自动申请

修改headscale配置文件

注释掉原来默认的官方url,在paths添加自定义的derp中继服务器配置

# /etc/headscale/config.yaml
derp:
  # List of externally available DERP maps encoded in JSON
  urls:
  #  - https://controlplane.tailscale.com/derpmap/default

  # Locally available DERP map files encoded in YAML
  #
  # This option is mostly interesting for people hosting
  # their own DERP servers:
  # https://tailscale.com/kb/1118/custom-derp-servers/
  #
  # paths:
  #   - /etc/headscale/derp-example.yaml
  paths:
    - /etc/headscale/derp.yaml

  # If enabled, a worker will be set up to periodically
  # refresh the given sources and update the derpmap
  # will be set up.
  auto_update_enabled: true

  # How often should we check for DERP updates?
  update_frequency: 24h

然后重启容器

docker restart headscale

访问https://headscale.域名/windows,出现下图显示说明部署成功

回到终端创建用户

#  创建用户
docker exec -it headscale headscale users create hiro

创建密钥

# reusable 参数代表可以复用,不加的话密钥只能用来一个客户端加入
docker exec -it headscale headscale preauthkeys create -e 10000d --reusable -u hiro
# 查看密钥 
docker exec -it headscale headscale preauthkeys list -u hiro

然后客户端安装好tailscale

例如windows

安装好后打开cmd,执行以下命令

参数可选 --advertise-routes=192.168.0.0/24,访问节点的指定网段设备。

tailscale login --login-server https://headscale.nekotech.xyz --accept-dns=false --accept-routes=false --authkey 替换为上一步生成的密钥 

执行网络测试命令,看到下图这样证明已连接成功

tailscale netcheck

然后继续再其他节点安装客户端并加入网络

#客户端可执行以下命令看到已加入的节点和具体IP
tailscale status

heascale 常用命令

  • namespace

headscale namespace list                      # 查看所有的namespace
headscale namespace create myspace            # 创建namespace
headscale namespace destroy myspace           # 删除namespace
headscale namespace rename myspace newspace   # 重命名namespace
  • node

headscale node list          # 列出所有的节点
headscale node ls -t         # 列出所有的节点,同时显示出tag信息
headscale -n myspace node ls # 只查看namespace为myspace下的节点
headscale node delete -i<ID> # 根据id删除指定的节点(id可用node list查询)
                             # 如 headscale nodes delete -i=2
headscale node tag -i=2 -t=tag:test # 给id为2的node设置tag为tag:test
  • route

headscale routes list -i=3    # 列出节点3的所有路由信息
headscale routes enable -i=3 -r=192.168.10.0/24 
                              # 将节点3的路由中信息为192.168.10.0/24的设置为true,
                              # 这样除了虚拟内网ip,原先的内网ip网段为192.168.10的也能访问了
  • preauthkeys

# preauthkeys主要是方便客户端快速接入,创建了preauthkeys后客户端直接使用该key就可以直接加入namespace
headscale -n default preauthkeys list # 查看名称为default的namespace中已经生成的preauthkeys 
headscale preauthkeys create -e 24h -n default # 给名称为default的namespace创建preauthkeys 
  • apikeys

# apikeys是为了客户端和headscale做http鉴权用的,http请求的时候需要设置头部authorization
# 值为固定的字符串"Bearer "加apikeys创建的key
headscale.exe apikeys create # 创建apikeys,在创建的时候需要记录下完整的值,后续查询出来的都是prefix
                             # 值类似于zs3NTt7G0w.pDWtOtaVx_mN9SzoM24Y02y6tfDzz5uysRHVxwJc1o4
headscale.exe apikeys list -o=json #查询headscale的apikeys,并将结果输出成json格式

最后附上官方tailscale客户端离线安装包各个平台的下载地址

pkgs.tailscale.com/stable/#spks