使用Headscale源码自行编译打包

说明

本文介绍如何自行打包编译 Headscale 源码,以及在编译源码的过程中可能出现的问题以及解决方法。

  • 操作系统: Windows 11 家庭中文版;WSL 2 Ubuntu24.04 LTS 系统。 本次编译源码使用了 wsl 2安装的 Ubutnu 24系统。
  • 源码目录: C:\Users\XXX\Documents\develop\0me\headscale 。 源码放在 Winodws系统中。
  • 源码下载: https://github.com/juanfont/headscale

环境准备

代码下载

推荐使用 git 下载,而不是 下载 压缩包的源码。我使用压缩包的源码进行编译的时候会出现很多错误,最后是通过go build -o headscale ./cmd/headscale 编译了一个可执行文件,但是无法通过 make build 编译。

使用下面的命令下载源码:

1
2
3
4
git clone https://github.com/juanfont/headscale.git

# 使用 v0.26.1 的 tag
git checkout -b release-v0.26.1 v0.26.1

然后复制根目录下的 config-example.yaml 重命名为 config.yaml

WSL

开启 WSL,并且安装 Ubuntu系统。

在当前计算机用户目录下,比如 C:\Users\XXX ,创建一个 .wslconfig 的文件,里面填入:

1
2
3
4
5
6
7
8
9
[wsl2]
nestedVirtualization=true
ipv6=true
[experimental]
autoMemoryReclaim=gradual # gradual | dropcache | disabled
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true

然后重启 wsl,这样 Ubuntu 系统就可以使用你本机的VPN网络了。 因为编译时需要下载一堆东西,没有外网VPN无法下载成功。

Nix安装

使用 root 账号安装 nixMulti-user 版本。

1
sh <(curl --proto '=https' --tlsv1.2 -L https://nixos.org/nix/install) --daemon

参考链接:https://nixos.org/download/

编译

编译时请从 root 账号切换到普通账号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 进入目录。windows电脑的目录在 wsl系统中 /mnt/c/ 目录下
cd /mnt/c/Users/XXX/Documents/develop/0me/headscale

# 准备环境。
nix develop

make generate
make test
make build

# 查看结果
ls -la result/

# 检查版本
cd ./result/bin
./headscale version # 会输出版本号

环境准备需要挺久,耐心等待。

make build 执行成功后,目录中会出现一个 result 目录(在windows系统中查看就是一个 0kb 大小的文件,实际在linux中是一个目录。

r
wr

编译异常汇总

以下编译的异常情况都是我使用 压缩的源代码编译出现的。使用 git 版本的源码编译没有如下问题。

问题1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 按照官方的编译步骤,使用 nix 编译。 make test 编译成功,但是 make build 出现如下错误:
djc@jetron-djc:/mnt/c/Users/DJC/Documents/develop/0me/headscale-0.26.1$ make build
nix build
error:
while calling the 'derivationStrict' builtin
at <nix/derivation-internal.nix>:37:12:
36|
37| strict = derivationStrict drvAttrs;
| ^
38|

while evaluating the derivation attribute 'name'
at /nix/store/qmm7hgw60vp7vj9lma95hl329d0j3n6n-source/pkgs/stdenv/generic/make-derivation.nix:438:13:
437| // (optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) {
438| name =
| ^
439| let

(stack trace truncated; use '--show-trace' to show the full, detailed trace)

error: attribute 'dirtyShortRev' missing
at /nix/store/wrx2gzxp6f5sdha4kswnpn6j8sqmfbnk-source/flake.nix:15:41:
14| }: let
15| headscaleVersion = self.shortRev or self.dirtyShortRev;
| ^
16| commitHash = self.rev or self.dirtyRev;
make: *** [Makefile:20: build] Error 1
  • 解决方法:

编辑 flake.nix 文件,

headscaleVersion = self.shortRev or self.dirtyShortRev; 修改成:

1
2
3
4
5
headscaleVersion = if self ? shortRev 
then self.shortRev
else if self ? dirtyShortRev
then self.dirtyShortRev
else "v0.26.1";

问题2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
djc@jetron-djc:/mnt/c/Users/DJC/Documents/develop/0me/headscale-0.26.1$ make build
nix build
warning: Git tree '/mnt/c/Users/DJC/Documents/develop/0me/headscale-0.26.1' is dirty
error: Cannot build '/nix/store/x0151wjd71c3icbvqrjrhmah4039cxrc-headscale-1d8abba-dirty.drv'.
Reason: builder failed with exit code 1.
Output paths:
/nix/store/w1kqv2j36dsixf5pm4v5lwf2wiwkrkhz-headscale-1d8abba-dirty
Last 25 log lines:
> Running phase: buildPhase
> Building subPackage ./cmd/headscale
> buildPhase completed in 52 seconds
> Running phase: checkPhase
>
> ----------------------------------------------------------------------
> FAIL: headscale_test.go:29: Suite.TestConfigFileLoading
>
> headscale_test.go:54:
> c.Assert(err, check.IsNil)
> ... value *fmt.wrapError = &fmt.wrapError{msg:"fatal error reading config file: open /build/headscale246087243/config.yaml: no such file or directory", err:(*fs.PathError)(0xc0003dfcb0)} ("fatal error reading config file: open /build/headscale246087243/config.yaml: no such file or directory")
>
>
> ----------------------------------------------------------------------
> FAIL: headscale_test.go:73: Suite.TestConfigLoading
>
> headscale_test.go:96:
> c.Assert(err, check.IsNil)
> ... value *fmt.wrapError = &fmt.wrapError{msg:"fatal error reading config file: Config File \"config\" Not Found in \"[/build/headscale4241716010]\"", err:viper.ConfigFileNotFoundError{name:"config", locations:"[/build/headscale4241716010]"}} ("fatal error reading config file: Config File \"config\" Not Found in \"[/build/headscale4241716010]\"")
>
> OOPS: 0 passed, 2 FAILED
> --- FAIL: Test (0.00s)
> FAIL
> FAIL github.com/juanfont/headscale/cmd/headscale 0.020s
> FAIL
For full logs, run:
nix log /nix/store/x0151wjd71c3icbvqrjrhmah4039cxrc-headscale-1d8abba-dirty.drv
make: *** [Makefile:20: build] Error 1

这个错误是因为测试阶段失败导致构建中断。测试失败的原因是找不到配置文件。

直接构建二进制文件:

1
2
3
cp config-example.yaml config.yaml
go mod tidy
go build -o headscale ./cmd/headscale

编译成功后,在项目目录下有个 headscale 文件,大概80多M。

问题3

1
2
root@jetron-djc:~# nix develop
error: experimental Nix feature 'nix-command' is disabled; add '--extra-experimental-features nix-command' to enable it

这个错误是因为 Nix 的 nix-command 功能是实验性的,默认被禁用了。

1
2
# 编辑配置文件
echo 'experimental-features = nix-command flakes' >> /etc/nix/nix.conf

使用 root 用户执行上面的命令即可。

问题4

1
2
3
root@jetron-djc:~# nix develop
path '/root' does not contain a 'flake.nix', searching up
error: could not find a flake.nix file

这个错误是因为 nix develop 命令需要在包含 flake.nix 文件的目录中运行,请 cd 到你项目的目录执行 nix develop

问题5

1
2
3
4
=== Failed
=== FAIL: hscontrol/db TestConstraints/no-duplicate-username-if-no-oidc-postgres (0.05s)
db_test.go:404: start postgres: initdb: initdb: error: cannot be run as root
initdb: hint: Please log in (using, e.g., "su") as the (unprivileged) user that will own the server process.

这个错误是因为 PostgreSQLinitdb 命令不能以 root 用户身份运行,这是出于安全考虑。测试代码试图以 root 用户初始化数据库,但被拒绝了。请使用普通用户 执行make build 命令。

手动安装相关依赖

1
2
3
4
5
6
# 安装 Buf
go install github.com/bufbuild/buf/cmd/buf@v1.55.1

# 安装 Protobuf
sudo apt update
sudo apt install protobuf-compiler