如何使用 docker-compose 在 5 分钟内设置 headscale 服务器

此 headscale 设置使用 sqlite - 对于简单用例,内存和 CPU 占用比 PostgreSQL 轻得多,我建议几乎任何安装都使用此方案:Headscale 不需要管理那么多请求,对于除最苛刻设置外的所有情况,使用 sqlite3 都可以。

首先,创建 headscale 和所有数据将驻留的目录(在此示例中我们使用 /opt/headscale)。

headscale_init_dirs.sh
sudo mkdir -p /opt/headscale

现在/opt/headscale 中运行以下脚本以初始化 headscale 所需的文件和目录:

headscale_init_files.sh
mkdir -p ./config
touch ./config/db.sqlite
curl https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml -o ./config/config.yaml

docker-compose 配置

***注意:***我们有一个用于 Traefik 作为反向代理的替代 docker-compose 配置,请参阅Traefik HTTPS 反向代理的 Headscale docker-compose 配置

现在是创建 /opt/headscale/docker-compose.yml 的时候了:

docker_compose_headscale.yml
services:
  headscale:
    image: headscale/headscale:latest
    volumes:
      - ./config:/etc/headscale/
      - ./data:/var/lib/headscale
    ports:
      - 27896:8080
    command: headscale serve
    restart: unless-stopped

这将配置 headscale 在端口 27896 上运行其 HTTP 服务器。你可以将此端口反向代理到你选择的域。

配置

现在我们应该编辑 config/config.yaml 中的服务器名称:

headscale_config.yaml
server_url: https://headscale.mydomain.com

注意你需要在此之后重启 tailscale

接下来,请参阅如何在 headscale 服务器上创建命名空间了解如何创建命名空间的详细信息。一旦创建了命名空间(类似于商业 tailscale 服务上的账户),你就可以继续连接客户端(客户端软件称为 tailscale),例如参见如何在 Linux 上将 tailscale 连接到 headscale 服务器

自动启动

使用我们之前文章在 10 秒内为你的 docker-compose 项目创建 systemd 服务中描述的方法,我们现在将使用 systemd 为 headscale 设置启动时自动启动。此命令也会立即启动它:

create_docker_compose_service.sh
curl -fsSL https://techoverflow.net/scripts/create-docker-compose-service.sh | sudo bash /dev/stdin

如何查看日志

使用此命令查看并跟踪日志:

docker_compose_logs.sh
docker-compose logs -f

示例输出:

headscale_docker_compose_logs.txt
headscale_1  | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
headscale_1  |
headscale_1  | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
headscale_1  |  - using env:    export GIN_MODE=release
headscale_1  |  - using code:   gin.SetMode(gin.ReleaseMode)
headscale_1  |
headscale_1  | [GIN-debug] GET    /metrics                  --> github.com/zsais/go-gin-prometheus.prometheusHandler.func1 (4 handlers)
headscale_1  | [GIN-debug] GET    /health                   --> github.com/juanfont/headscale.(*Headscale).Serve.func2 (4 handlers)
headscale_1  | [GIN-debug] GET    /key                      --> github.com/juanfont/headscale.(*Headscale).KeyHandler-fm (4 handlers)
headscale_1  | [GIN-debug] [GIN-debug] GET    /register                 --> github.com/juanfont/headscale.(*Headscale).RegisterWebAPI-fm (4 handlers)
headscale_1  | [GIN-debug] POST   /machine/:id/map          --> github.com/juanfont/headscale.(*Headscale).PollNetMapHandler-fm (5 handlers)
headscale_1  | [GIN-debug] POST   /machine/:id              --> github.com/juanfont/headscale.(*Headscale).RegistrationHandler-fm (5 handlers)
headscale_1  | [GIN-debug] GET    /oidc/register/:mkey      --> github.com/juanfont/headscale.(*Headscale).RegisterOIDC-fm (5 handlers)
headscale_1  | [GIN-debug] GET    /oidc/callback            --> github.com/juanfont/headscale.(*Headscale).OIDCCallback-fm (5 handlers)
headscale_1  | [GIN-debug] GET    /apple                    --> github.com/juanfont/headscale.SwaggerUI (4 handlers)
headscale_1  | [GIN-debug] GET    /apple/:platform          --> github.com/juanfont/headscale.(*Headscale).AppleMobileConfig-fm (4 handlers)
headscale_1  | [GIN-debug] GET    /swagger                  --> github.com/juanfont/headscale.SwaggerUI (4 handlers)
headscale_1  | [GIN-debug] GET    /swagger/v1/openapiv2.json --> github.com/juanfont/headscale.SwaggerAPIv1 (4 handlers)
headscale_1  | [GIN-debug] GET    /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] POST   /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] PUT    /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] PATCH  /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] HEAD   /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] OPTIONS /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] DELETE /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] CONNECT /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | [GIN-debug] TRACE  /api/v1/*any              --> github.com/gin-gonic/gin.WrapF.func1 (5 handlers)
headscale_1  | 2022-01-16T19:04:04Z WRN Listening without TLS but ServerURL does not start with http://
headscale_1  | 2022-01-16T19:04:04Z INF listening and serving (multiplexed HTTP and gRPC) on: 0.0.0.0:8080
headscale_1  | 2022-01-16T19:04:04Z INF Setting up a DERPMap update worker frequency=86400000
headscale_1  | 2022-01-16T19:04:04Z INF listening and serving (multiplexed HTTP and gRPC) on: 0.0.0.0:8080
headscale_1  | 2022-01-16T19:04:04Z INF Setting up a DERPMap update worker frequency=86400000

Check out similar posts by category: Headscale, Networking, VPN, Wireguard