Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nixos/netbird: harden and extend options #287236

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nazarewk
Copy link
Member

@nazarewk nazarewk commented Feb 8, 2024

Description of changes

I have recently extensively tested and fixed all features of Netbird in my own implementation of multi-instance Netbird installations.

While doing so I discovered another multi-instance implementation got merged into nixpkgs #246055 which is slightly different, but still a solid base to upstream the rest of my changes:

  • running as DynamicUser it's own user with minimal set of permissions
    • it was there before, but was lacking some of capabilities,
  • made some configurations situational
  • add more unmanaged interface configurations
  • quality of life improvements:
    • configure log level for each interface
    • optionally turn off starting during boot
    • openFirewall by default
    • add shortcuts/wrappers for each created instance

I think it's a pretty good time to upstream, because I will be extensively using it at work: just launched my first Colmena-managed NixOS into GCE.

There are plans to support multi-account connections on the same daemon in Q2/2024 (see the slack message), but it's not known what shape it will take at all.

I decided to implement following significant changes:

  • instances must specify a port they will be listening on as it doesn't make much sense to give an immediately conflicting default,
  • aliased tunnels to clients, because a word tunnel does not exist in Netbird's nomenclature (unlike some other VPNs) and is pretty misleading. Also clients.* play nicely with my plan to implement a server in near future.
  • skipped destructuring expressions (eg: {name, ...}: name -> client: client.name) because they make the code very hard to follow and update with increased number of options,

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 👍 reaction to pull requests you find important.

@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Feb 8, 2024
@ofborg ofborg bot added 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10 labels Feb 8, 2024
@nazarewk nazarewk changed the title nixos/netbird: run as DynamicUser with more configuration options nixos/netbird: bring back DynamicUser with more configuration options Feb 9, 2024
@nazarewk nazarewk marked this pull request as draft February 9, 2024 08:43
@nazarewk nazarewk changed the title nixos/netbird: bring back DynamicUser with more configuration options nixos/netbird: harden and extend options Feb 9, 2024
@nazarewk nazarewk force-pushed the netbird-improvements branch 5 times, most recently from 0cf761f to 4179661 Compare February 9, 2024 12:47
@nazarewk nazarewk marked this pull request as ready for review February 9, 2024 12:54
nazarewk added a commit to nazarewk-iac/nix-configs that referenced this pull request Feb 9, 2024
@Tom-Hubrecht Tom-Hubrecht assigned mlvzk and unassigned mlvzk Feb 10, 2024
nixos/modules/services/networking/netbird.nix Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
Comment on lines 96 to 124
suffix = mkOption {
type = str;
default = "-${name}";
description = ''
Suffix to use for this further naming of the service pieces.
'';
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems overly complicated, as it is only used for defaults, you should use the name for this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also used for the wrapper, but yeah might make more sense to not drop -wt0 from the default config. The raw "unwrapped" package should work with it anyway.

Copy link
Member Author

@nazarewk nazarewk Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it made more sense when there were 3 wrappers

nixos/modules/services/networking/netbird.md Outdated Show resolved Hide resolved
@@ -12,6 +12,7 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
};
};

# TODO: confirm DynamicUser is working if/after netbird server is implemented
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no netbird server in this PR

Copy link
Member Author

@nazarewk nazarewk Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but it is very much relevant for the test, there is no confirmation the client actually works until we have a server to connect to.

Comment on lines 179 to 192
exports = pipe config.environment [
(mapAttrsToList (name: default:
# Couldn't default with `''${${name}:${escapeShellArg default}}`
# because `escapeShellArg` wraps values in single quotes,
# which in turn works differenty (or rather doesn't) than double-quotes
# in this shell parameter expansion
''test "''${${name}+X}" == X || export ${toShellVar name default}''))
(concatStringsSep "\n")
];
in
pkgs.writeShellScriptBin "netbird${config.suffix}" ''
${exports}
${lib.getExe' cfg.package "netbird"} "$@"
'';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very weird, nixpkgs has a machinery already to wrap programs c.f. https://nixos.org/manual/nixpkgs/stable/#fun-wrapProgram

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure it would be significantly longer with wrapProgram, something like:

mkDerivation {
	pname = "xxx";
    installPhase = 
	    let
	  		exports = pipe config.environment [
	          (mapAttrsToList (name: default:
	            "--set-default '${name}' '${default}'"))
	          (concatStringsSep " ")
	        ];
		in
		"wrapProgram ${lib.getExe' cfg.package "netbird"} $out/bin/netbird${config.suffix} ${exports}";
}

actually makes more sense after prototyping it and seeing with own eyes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do something like

    stdenv.mkDerivation {
      intallPhase = ''
        wrapProgram ${lib.getExe cfg.package} $out/bin/netbird${config.suffix} ${
          concatMapStringsSep " " ({ name, value }: "--set-default '${name}' '${default}'") (
            attrsToList config.environment
          )
        }
      '';

The issue I had was not because of the size of the code, but reinventing the wheel ^^

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not so short anymore:

let
  makeWrapperArgs = flatten (mapAttrsToList
    (key: value: [ "--set-default" key value ])
    config.environment
  );
in
pkgs.stdenv.mkDerivation {
  name = "${cfg.package.name}-wrapper-${name}";
  meta.mainProgram = config.name;
  nativeBuildInputs = with pkgs; [ makeWrapper ];
  phases = [ "installPhase" ];
  installPhase = ''
    mkdir -p "$out/bin"
    makeWrapper ${lib.getExe cfg.package} "$out/bin/${config.name}" \
      ${escapeShellArgs makeWrapperArgs}
  '';
}


A single daemon is fully operational.

Multiple daemons will interfere with each other's DNS resolution, but otherwise should remain operational.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the networks have different domains, there is no interference, the only issue is when then share the same domain

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the domain is configurable at all on the Netbird server side?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is when you self-host your server

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI:

Hello[@nazarewk, we plan a custom DNS zone support coming next quarter. That would allow you to create custom domains for applications and peers

https://netbirdio.slack.com/archives/C02KHAE8VLZ/p1707820381270479?thread_ts=1707819591.188209&cid=C02KHAE8VLZ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom DNS zone support is already implemented for self-hosted,

        ${pkgs.netbird}/bin/netbird-mgmt management \
        --dns-domain dns.domain

Will place every machine under dns.domain subdomain: machine1.dns.domain, machine2.dns.domain

nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
nixos/modules/services/networking/netbird.nix Outdated Show resolved Hide resolved
@nazarewk nazarewk force-pushed the netbird-improvements branch 3 times, most recently from a734f1e to 35a7c67 Compare February 13, 2024 11:08
@wegank wegank added the 2.status: merge conflict This PR has merge conflicts with the target branch label Jul 4, 2024
@nazarewk nazarewk force-pushed the netbird-improvements branch 2 times, most recently from 6947525 to 41ea15c Compare September 19, 2024 13:19
@ofborg ofborg bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Sep 19, 2024
@nazarewk nazarewk force-pushed the netbird-improvements branch 3 times, most recently from b11a6de to 43d2daf Compare September 26, 2024 08:49
@wegank wegank removed the 12.approved-by: package-maintainer This PR was reviewed and approved by a maintainer listed in the package label Oct 29, 2024
@wegank wegank added the 2.status: merge conflict This PR has merge conflicts with the target branch label Nov 9, 2024
@ofborg ofborg bot removed the 2.status: merge conflict This PR has merge conflicts with the target branch label Nov 12, 2024
Copy link
Contributor

@PatrickDaG PatrickDaG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Module looks great. Hope it gets merged soon, been long enough.
I would like to test this more myself, but I'm working on a rewrite of the netbird-server modules right now and while I don't think they actually conflict, the merges do.

@@ -711,7 +711,7 @@ Use `services.pipewire.extraConfig` or `services.pipewire.configPackages` for Pi
and `services.kavita.settings.IpAddresses`. The file at `services.kavita.tokenKeyFile` now needs to contain a secret with
512+ bits instead of 128+ bits.

- `services.netbird` now allows running multiple tunnels in parallel through [`services.netbird.tunnels`](#opt-services.netbird.tunnels).
- `services.netbird` now allows running multiple tunnels in parallel through [`services.netbird.tunnels`](#opt-services.netbird.clients).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably move this and the 2411 release notes to 2505.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honest, this PR is hanging for so many months I lost hope it will ever get merged and I stopped trying to chase people able to merge it.

Copy link
Member Author

@nazarewk nazarewk Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make the "proper" release notes when some of the maintainers able to give it review and merge pops up.
The code itself was written around 23.11 and already missed 2 releases.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know how frustrating a long running PR can be. The unfortunate thing is that any committer who comes along will see that this is missing proper release notes, and then can't merge it. So this will only delay it further.

I fully understand if you say that this requires too much work to keep up in the long term. Let me know if you need support with anything, otherwise I'd also offer pick this PR up if you don't want to keep working on it.


documentation = [ "https://netbird.io/docs/" ];
environment.etc = toClientAttrs (client: nameValuePair "netbird-${client.name}/config.d/50-nixos.json" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you plan to add more override files, or why do you first write the file in /etc and later iterate over the one file? I think it would be simpler to skip this and directly access the file from the nix-store in the derivation, skipping one indirection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using those on some of my machines and while testing stuff.

makeWrapper ${lib.getExe cfg.package} "$out/bin/netbird-${name}" \
${escapeShellArgs makeWrapperArgs}
''
(optionalString cfg.ui.enable ''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the client.ui.enable option then be removed as it doesn't do anything?


documentation = [ "https://netbird.io/docs/" ];
environment.etc = toClientAttrs (client: nameValuePair "netbird-${client.name}/config.d/50-nixos.json" {
text = builtins.toJSON client.config;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probs would be better to use formatType.generate "config.json" cfg.config; since you're using the json format type already

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think that's necessary, I think the generation uses jq with a separate derivation underneath.

@nazarewk nazarewk force-pushed the netbird-improvements branch 2 times, most recently from c87df07 to 7f1bf2d Compare November 15, 2024 15:11
Directory storing the netbird configuration.
Start the service with the system.

As of 2024-02-13 it is not possible to start a Netbird client daemon without immediately
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an disable-auto-connect flag but it seems to only apply to netbird up, the link however seems to have run stale as there is no mention of such a feature being planned as far as I can see.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotta look into it, I'm using some form of this in my configs successfully

@nazarewk nazarewk force-pushed the netbird-improvements branch 2 times, most recently from 9c8d2df to cf0bb20 Compare November 25, 2024 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: changelog 8.has: documentation 8.has: module (update) This PR changes an existing module in `nixos/` 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin 10.rebuild-linux: 1-10
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants