Skip to content

Commit 086d855

Browse files
authored
netbird: 0.49.0 -> 0.54.0 + split up + relicense (#431976)
2 parents 1c39e58 + f1277e5 commit 086d855

File tree

10 files changed

+171
-70
lines changed

10 files changed

+171
-70
lines changed

nixos/doc/manual/release-notes/rl-2511.section.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,8 @@
187187

188188
- `services.monero` now includes the `environmentFile` option for adding secrets to the Monero daemon config.
189189

190+
- `services.netbird.server` now uses dedicated packages split out due to relicensing of server components to AGPLv3 with version `0.53.0`,
191+
190192
- The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip).
191193
With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation.
192194

nixos/modules/services/networking/netbird/management.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ in
139139
options.services.netbird.server.management = {
140140
enable = mkEnableOption "Netbird Management Service";
141141

142-
package = mkPackageOption pkgs "netbird" { };
142+
package = mkPackageOption pkgs "netbird-management" { };
143143

144144
domain = mkOption {
145145
type = str;

nixos/modules/services/networking/netbird/signal.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ in
3131
options.services.netbird.server.signal = {
3232
enable = mkEnableOption "Netbird's Signal Service";
3333

34-
package = mkPackageOption pkgs "netbird" { };
34+
package = mkPackageOption pkgs "netbird-signal" { };
3535

3636
enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird signal service";
3737

nixos/tests/netbird.nix

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,50 +7,94 @@
77
];
88

99
nodes = {
10-
clients =
10+
node =
1111
{ ... }:
1212
{
1313
services.netbird.enable = true;
1414
services.netbird.clients.custom.port = 51819;
1515
};
1616
};
1717

18-
# TODO: confirm the whole solution is working end-to-end when netbird server is implemented
19-
testScript = ''
20-
start_all()
21-
def did_start(node, name, interval=0.5, timeout=10):
22-
node.wait_for_unit(f"{name}.service")
23-
node.wait_for_file(f"/var/run/{name}/sock")
24-
# `netbird status` returns a full "Disconnected" status during initialization
25-
# only after a while passes it starts returning "NeedsLogin" help message
26-
27-
start = time.time()
28-
output = node.succeed(f"{name} status")
29-
while "Disconnected" in output and (time.time() - start) < timeout:
30-
time.sleep(interval)
31-
output = node.succeed(f"{name} status")
32-
assert "NeedsLogin" in output
33-
34-
did_start(clients, "netbird")
35-
did_start(clients, "netbird-custom")
36-
'';
37-
3818
/*
39-
`netbird status` used to print `Daemon status: NeedsLogin`
40-
https://github.com/netbirdio/netbird/blob/23a14737974e3849fa86408d136cc46db8a885d0/client/cmd/status.go#L154-L164
41-
as the first line, but now it is just:
19+
Historically waiting for the NetBird client daemon initialization helped catch number of bugs with the service,
20+
so we keep try to keep it here in as much details as it makes sense.
4221
43-
Daemon version: 0.26.3
44-
CLI version: 0.26.3
45-
Management: Disconnected
22+
Initially `netbird status` returns a "Disconnected" messages:
23+
OS: linux/amd64
24+
Daemon version: 0.54.0
25+
CLI version: 0.54.0
26+
Profile: default
27+
Management: Disconnected, reason: rpc error: code = FailedPrecondition desc = failed connecting to Management Service : context deadline exceeded
4628
Signal: Disconnected
4729
Relays: 0/0 Available
4830
Nameservers: 0/0 Available
4931
FQDN:
5032
NetBird IP: N/A
5133
Interface type: N/A
5234
Quantum resistance: false
53-
Routes: -
35+
Lazy connection: false
36+
Networks: -
37+
Forwarding rules: 0
5438
Peers count: 0/0 Connected
39+
40+
After a while passes it should start returning "NeedsLogin" help message.
41+
42+
As of ~0.53.0+ in ~30 second intervals the `netbird status` instead of "NeedsLogin" it briefly (for under 2 seconds) crashes with:
43+
44+
Error: status failed: failed connecting to Management Service : context deadline exceeded
45+
46+
This might be related to the following log line:
47+
48+
2025-08-11T15:03:25Z ERRO shared/management/client/grpc.go:65: failed creating connection to Management Service: context deadline exceeded
5549
*/
50+
# TODO: confirm the whole solution is working end-to-end when netbird server is implemented
51+
testScript = ''
52+
import textwrap
53+
import time
54+
55+
start_all()
56+
57+
def run_with_debug(node, cmd, check=True, display=True, **kwargs):
58+
cmd = f"{cmd} 2>&1"
59+
start = time.time()
60+
ret, output = node.execute(cmd, **kwargs)
61+
duration = time.time() - start
62+
txt = f">>> {cmd=} {ret=} {duration=:.2f}:\n{textwrap.indent(output, '... ')}"
63+
if check:
64+
assert ret == 0, txt
65+
if display:
66+
print(txt)
67+
return ret, output
68+
69+
def wait_until_rcode(node, cmd, rcode=0, retries=30, **kwargs):
70+
def check_success(_last_try):
71+
nonlocal output
72+
ret, output = run_with_debug(node, cmd, **kwargs)
73+
return ret == rcode
74+
75+
kwargs.setdefault('check', False)
76+
output = None
77+
with node.nested(f"waiting for {cmd=} to exit with {rcode=}"):
78+
retry(check_success, retries)
79+
return output
80+
81+
instances = ["netbird", "netbird-custom"]
82+
83+
for name in instances:
84+
node.wait_for_unit(f"{name}.service")
85+
node.wait_for_file(f"/var/run/{name}/sock")
86+
87+
for name in instances:
88+
wait_until_rcode(node, f"{name} status |& grep -C20 Disconnected", 0, retries=5)
89+
''
90+
# The status used to turn into `NeedsLogin`, but recently started crashing instead.
91+
# leaving the snippets in here, in case some update goes back to the old behavior and can be tested again
92+
+ lib.optionalString false ''
93+
for name in instances:
94+
#wait_until_rcode(node, f"{name} status |& grep -C20 NeedsLogin", 0, retries=20)
95+
output = wait_until_rcode(node, f"{name} status", 1, retries=61)
96+
msg = "Error: status failed: failed connecting to Management Service : context deadline exceeded"
97+
assert output.strip() == msg, f"expected {msg=}, got {output=} instead"
98+
wait_until_rcode(node, f"{name} status |& grep -C20 Disconnected", 0, retries=10)
99+
'';
56100
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{ netbird }:
2+
3+
netbird.override {
4+
componentName = "management";
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{ netbird }:
2+
3+
netbird.override {
4+
componentName = "relay";
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{ netbird }:
2+
3+
netbird.override {
4+
componentName = "signal";
5+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{ netbird }:
22

33
netbird.override {
4-
ui = true;
4+
componentName = "ui";
55
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{ netbird }:
2+
3+
netbird.override {
4+
componentName = "upload";
5+
}

pkgs/by-name/ne/netbird/package.nix

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,80 @@
1212
libX11,
1313
libXcursor,
1414
libXxf86vm,
15-
ui ? false,
1615
netbird-ui,
1716
versionCheckHook,
17+
componentName ? "client",
1818
}:
1919
let
20-
modules =
21-
if ui then
22-
{
23-
"client/ui" = "netbird-ui";
24-
}
25-
else
26-
{
27-
client = "netbird";
28-
management = "netbird-mgmt";
29-
signal = "netbird-signal";
30-
};
20+
/*
21+
License tagging is based off:
22+
- https://github.com/netbirdio/netbird/blob/9e95841252c62b50ae93805c8dfd2b749ac95ea7/LICENSES/REUSE.toml
23+
- https://github.com/netbirdio/netbird/blob/9e95841252c62b50ae93805c8dfd2b749ac95ea7/LICENSE#L1-L2
24+
*/
25+
availableComponents = {
26+
client = {
27+
module = "client";
28+
binaryName = "netbird";
29+
license = lib.licenses.bsd3;
30+
versionCheckProgramArg = "version";
31+
hasCompletion = true;
32+
};
33+
ui = {
34+
module = "client/ui";
35+
binaryName = "netbird-ui";
36+
license = lib.licenses.bsd3;
37+
};
38+
upload = {
39+
module = "upload-server";
40+
binaryName = "netbird-upload";
41+
license = lib.licenses.bsd3;
42+
};
43+
management = {
44+
module = "management";
45+
binaryName = "netbird-mgmt";
46+
license = lib.licenses.agpl3Only;
47+
versionCheckProgramArg = "--version";
48+
hasCompletion = true;
49+
};
50+
signal = {
51+
module = "signal";
52+
binaryName = "netbird-signal";
53+
license = lib.licenses.agpl3Only;
54+
hasCompletion = true;
55+
};
56+
relay = {
57+
module = "relay";
58+
binaryName = "netbird-relay";
59+
license = lib.licenses.agpl3Only;
60+
};
61+
};
62+
isUI = componentName == "ui";
63+
component = availableComponents.${componentName};
3164
in
3265
buildGoModule (finalAttrs: {
33-
pname = "netbird";
34-
version = "0.49.0";
66+
pname = "netbird-${componentName}";
67+
version = "0.54.0";
3568

3669
src = fetchFromGitHub {
3770
owner = "netbirdio";
3871
repo = "netbird";
3972
tag = "v${finalAttrs.version}";
40-
hash = "sha256-Hv0A9/NTMzRAf9YvYGvRLyy2gdigF9y2NfylE8bLcTw=";
73+
hash = "sha256-qKYJa7q7scEbbxLHaosaurrjXR5ABxCAnuUcy80yKEc=";
4174
};
4275

43-
vendorHash = "sha256-t/X/muMwHVwg8Or+pFTSEQEsnkKLuApoVUmMhyCImWI=";
76+
vendorHash = "sha256-uVVm+iDGP2eZ5GVXWJrWZQ7LpHdZccRIiHPIFs6oAPo=";
4477

45-
nativeBuildInputs = [ installShellFiles ] ++ lib.optional ui pkg-config;
78+
nativeBuildInputs = [ installShellFiles ] ++ lib.optional isUI pkg-config;
4679

47-
buildInputs = lib.optionals (stdenv.hostPlatform.isLinux && ui) [
80+
buildInputs = lib.optionals (stdenv.hostPlatform.isLinux && isUI) [
4881
gtk3
4982
libayatana-appindicator
5083
libX11
5184
libXcursor
5285
libXxf86vm
5386
];
5487

55-
subPackages = lib.attrNames modules;
88+
subPackages = [ component.module ];
5689

5790
ldflags = [
5891
"-s"
@@ -73,35 +106,36 @@ buildGoModule (finalAttrs: {
73106
'';
74107

75108
postInstall =
76-
lib.concatStringsSep "\n" (
77-
lib.mapAttrsToList (
78-
module: binary:
79-
''
80-
mv $out/bin/${lib.last (lib.splitString "/" module)} $out/bin/${binary}
109+
let
110+
builtBinaryName = lib.last (lib.splitString "/" component.module);
111+
in
112+
''
113+
mv $out/bin/${builtBinaryName} $out/bin/${component.binaryName}
114+
''
115+
+
116+
lib.optionalString
117+
(stdenv.buildPlatform.canExecute stdenv.hostPlatform && (component.hasCompletion or false))
81118
''
82-
+ lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform && !ui) ''
83-
installShellCompletion --cmd ${binary} \
84-
--bash <($out/bin/${binary} completion bash) \
85-
--fish <($out/bin/${binary} completion fish) \
86-
--zsh <($out/bin/${binary} completion zsh)
119+
installShellCompletion --cmd ${component.binaryName} \
120+
--bash <($out/bin/${component.binaryName} completion bash) \
121+
--fish <($out/bin/${component.binaryName} completion fish) \
122+
--zsh <($out/bin/${component.binaryName} completion zsh)
87123
''
88-
) modules
89-
)
90-
+ lib.optionalString (stdenv.hostPlatform.isLinux && ui) ''
124+
# assemble & adjust netbird.desktop files for the GUI
125+
+ lib.optionalString (stdenv.hostPlatform.isLinux && isUI) ''
91126
install -Dm644 "$src/client/ui/assets/netbird-systemtray-connected.png" "$out/share/pixmaps/netbird.png"
92127
install -Dm644 "$src/client/ui/build/netbird.desktop" "$out/share/applications/netbird.desktop"
93128
94129
substituteInPlace $out/share/applications/netbird.desktop \
95-
--replace-fail "Exec=/usr/bin/netbird-ui" "Exec=$out/bin/netbird-ui"
130+
--replace-fail "Exec=/usr/bin/netbird-ui" "Exec=$out/bin/${component.binaryName}"
96131
'';
97132

98133
nativeInstallCheckInputs = [
99134
versionCheckHook
100135
];
101-
versionCheckProgram = "${placeholder "out"}/bin/${finalAttrs.meta.mainProgram}";
102-
versionCheckProgramArg = "version";
103-
# Disabled for the `netbird-ui` version because it does a network request.
104-
doInstallCheck = !ui;
136+
versionCheckProgram = "${placeholder "out"}/bin/${component.binaryName}";
137+
versionCheckProgramArg = component.versionCheckProgramArg or "version";
138+
doInstallCheck = component ? versionCheckProgramArg;
105139

106140
passthru = {
107141
tests = {
@@ -115,11 +149,12 @@ buildGoModule (finalAttrs: {
115149
homepage = "https://netbird.io";
116150
changelog = "https://github.com/netbirdio/netbird/releases/tag/v${finalAttrs.version}";
117151
description = "Connect your devices into a single secure private WireGuard®-based mesh network with SSO/MFA and simple access controls";
118-
license = lib.licenses.bsd3;
152+
license = component.license;
119153
maintainers = with lib.maintainers; [
154+
nazarewk
120155
saturn745
121156
loc
122157
];
123-
mainProgram = if ui then "netbird-ui" else "netbird";
158+
mainProgram = component.binaryName;
124159
};
125160
})

0 commit comments

Comments
 (0)