netbird: 0.49.0 -> 0.54.0 + split up + relicense (#431976)

authored by Paul Haerle and committed by GitHub 086d8553 1c39e588

+171 -70
+2
nixos/doc/manual/release-notes/rl-2511.section.md
··· 187 188 - `services.monero` now includes the `environmentFile` option for adding secrets to the Monero daemon config. 189 190 - The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip). 191 With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation. 192
··· 187 188 - `services.monero` now includes the `environmentFile` option for adding secrets to the Monero daemon config. 189 190 + - `services.netbird.server` now uses dedicated packages split out due to relicensing of server components to AGPLv3 with version `0.53.0`, 191 + 192 - The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip). 193 With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation. 194
+1 -1
nixos/modules/services/networking/netbird/management.nix
··· 139 options.services.netbird.server.management = { 140 enable = mkEnableOption "Netbird Management Service"; 141 142 - package = mkPackageOption pkgs "netbird" { }; 143 144 domain = mkOption { 145 type = str;
··· 139 options.services.netbird.server.management = { 140 enable = mkEnableOption "Netbird Management Service"; 141 142 + package = mkPackageOption pkgs "netbird-management" { }; 143 144 domain = mkOption { 145 type = str;
+1 -1
nixos/modules/services/networking/netbird/signal.nix
··· 31 options.services.netbird.server.signal = { 32 enable = mkEnableOption "Netbird's Signal Service"; 33 34 - package = mkPackageOption pkgs "netbird" { }; 35 36 enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird signal service"; 37
··· 31 options.services.netbird.server.signal = { 32 enable = mkEnableOption "Netbird's Signal Service"; 33 34 + package = mkPackageOption pkgs "netbird-signal" { }; 35 36 enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird signal service"; 37
+72 -28
nixos/tests/netbird.nix
··· 7 ]; 8 9 nodes = { 10 - clients = 11 { ... }: 12 { 13 services.netbird.enable = true; ··· 15 }; 16 }; 17 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 - 38 /* 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: 42 43 - Daemon version: 0.26.3 44 - CLI version: 0.26.3 45 - Management: Disconnected 46 Signal: Disconnected 47 Relays: 0/0 Available 48 Nameservers: 0/0 Available ··· 50 NetBird IP: N/A 51 Interface type: N/A 52 Quantum resistance: false 53 - Routes: - 54 Peers count: 0/0 Connected 55 */ 56 }
··· 7 ]; 8 9 nodes = { 10 + node = 11 { ... }: 12 { 13 services.netbird.enable = true; ··· 15 }; 16 }; 17 18 /* 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. 21 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 28 Signal: Disconnected 29 Relays: 0/0 Available 30 Nameservers: 0/0 Available ··· 32 NetBird IP: N/A 33 Interface type: N/A 34 Quantum resistance: false 35 + Lazy connection: false 36 + Networks: - 37 + Forwarding rules: 0 38 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 49 */ 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 + ''; 100 }
+5
pkgs/by-name/ne/netbird-management/package.nix
···
··· 1 + { netbird }: 2 + 3 + netbird.override { 4 + componentName = "management"; 5 + }
+5
pkgs/by-name/ne/netbird-relay/package.nix
···
··· 1 + { netbird }: 2 + 3 + netbird.override { 4 + componentName = "relay"; 5 + }
+5
pkgs/by-name/ne/netbird-signal/package.nix
···
··· 1 + { netbird }: 2 + 3 + netbird.override { 4 + componentName = "signal"; 5 + }
+1 -1
pkgs/by-name/ne/netbird-ui/package.nix
··· 1 { netbird }: 2 3 netbird.override { 4 - ui = true; 5 }
··· 1 { netbird }: 2 3 netbird.override { 4 + componentName = "ui"; 5 }
+5
pkgs/by-name/ne/netbird-upload/package.nix
···
··· 1 + { netbird }: 2 + 3 + netbird.override { 4 + componentName = "upload"; 5 + }
+74 -39
pkgs/by-name/ne/netbird/package.nix
··· 12 libX11, 13 libXcursor, 14 libXxf86vm, 15 - ui ? false, 16 netbird-ui, 17 versionCheckHook, 18 }: 19 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 - }; 31 in 32 buildGoModule (finalAttrs: { 33 - pname = "netbird"; 34 - version = "0.49.0"; 35 36 src = fetchFromGitHub { 37 owner = "netbirdio"; 38 repo = "netbird"; 39 tag = "v${finalAttrs.version}"; 40 - hash = "sha256-Hv0A9/NTMzRAf9YvYGvRLyy2gdigF9y2NfylE8bLcTw="; 41 }; 42 43 - vendorHash = "sha256-t/X/muMwHVwg8Or+pFTSEQEsnkKLuApoVUmMhyCImWI="; 44 45 - nativeBuildInputs = [ installShellFiles ] ++ lib.optional ui pkg-config; 46 47 - buildInputs = lib.optionals (stdenv.hostPlatform.isLinux && ui) [ 48 gtk3 49 libayatana-appindicator 50 libX11 ··· 52 libXxf86vm 53 ]; 54 55 - subPackages = lib.attrNames modules; 56 57 ldflags = [ 58 "-s" ··· 73 ''; 74 75 postInstall = 76 - lib.concatStringsSep "\n" ( 77 - lib.mapAttrsToList ( 78 - module: binary: 79 - '' 80 - mv $out/bin/${lib.last (lib.splitString "/" module)} $out/bin/${binary} 81 '' 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) 87 '' 88 - ) modules 89 - ) 90 - + lib.optionalString (stdenv.hostPlatform.isLinux && ui) '' 91 install -Dm644 "$src/client/ui/assets/netbird-systemtray-connected.png" "$out/share/pixmaps/netbird.png" 92 install -Dm644 "$src/client/ui/build/netbird.desktop" "$out/share/applications/netbird.desktop" 93 94 substituteInPlace $out/share/applications/netbird.desktop \ 95 - --replace-fail "Exec=/usr/bin/netbird-ui" "Exec=$out/bin/netbird-ui" 96 ''; 97 98 nativeInstallCheckInputs = [ 99 versionCheckHook 100 ]; 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; 105 106 passthru = { 107 tests = { ··· 115 homepage = "https://netbird.io"; 116 changelog = "https://github.com/netbirdio/netbird/releases/tag/v${finalAttrs.version}"; 117 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; 119 maintainers = with lib.maintainers; [ 120 saturn745 121 loc 122 ]; 123 - mainProgram = if ui then "netbird-ui" else "netbird"; 124 }; 125 })
··· 12 libX11, 13 libXcursor, 14 libXxf86vm, 15 netbird-ui, 16 versionCheckHook, 17 + componentName ? "client", 18 }: 19 let 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}; 64 in 65 buildGoModule (finalAttrs: { 66 + pname = "netbird-${componentName}"; 67 + version = "0.54.0"; 68 69 src = fetchFromGitHub { 70 owner = "netbirdio"; 71 repo = "netbird"; 72 tag = "v${finalAttrs.version}"; 73 + hash = "sha256-qKYJa7q7scEbbxLHaosaurrjXR5ABxCAnuUcy80yKEc="; 74 }; 75 76 + vendorHash = "sha256-uVVm+iDGP2eZ5GVXWJrWZQ7LpHdZccRIiHPIFs6oAPo="; 77 78 + nativeBuildInputs = [ installShellFiles ] ++ lib.optional isUI pkg-config; 79 80 + buildInputs = lib.optionals (stdenv.hostPlatform.isLinux && isUI) [ 81 gtk3 82 libayatana-appindicator 83 libX11 ··· 85 libXxf86vm 86 ]; 87 88 + subPackages = [ component.module ]; 89 90 ldflags = [ 91 "-s" ··· 106 ''; 107 108 postInstall = 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)) 118 '' 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) 123 '' 124 + # assemble & adjust netbird.desktop files for the GUI 125 + + lib.optionalString (stdenv.hostPlatform.isLinux && isUI) '' 126 install -Dm644 "$src/client/ui/assets/netbird-systemtray-connected.png" "$out/share/pixmaps/netbird.png" 127 install -Dm644 "$src/client/ui/build/netbird.desktop" "$out/share/applications/netbird.desktop" 128 129 substituteInPlace $out/share/applications/netbird.desktop \ 130 + --replace-fail "Exec=/usr/bin/netbird-ui" "Exec=$out/bin/${component.binaryName}" 131 ''; 132 133 nativeInstallCheckInputs = [ 134 versionCheckHook 135 ]; 136 + versionCheckProgram = "${placeholder "out"}/bin/${component.binaryName}"; 137 + versionCheckProgramArg = component.versionCheckProgramArg or "version"; 138 + doInstallCheck = component ? versionCheckProgramArg; 139 140 passthru = { 141 tests = { ··· 149 homepage = "https://netbird.io"; 150 changelog = "https://github.com/netbirdio/netbird/releases/tag/v${finalAttrs.version}"; 151 description = "Connect your devices into a single secure private WireGuard®-based mesh network with SSO/MFA and simple access controls"; 152 + license = component.license; 153 maintainers = with lib.maintainers; [ 154 + nazarewk 155 saturn745 156 loc 157 ]; 158 + mainProgram = component.binaryName; 159 }; 160 })