diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md
index 3bb993ec33c6..91a91beb34d6 100644
--- a/nixos/doc/manual/release-notes/rl-2405.section.md
+++ b/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -709,7 +709,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).
 
 - `services.nginx.virtualHosts` using `forceSSL` or
   `globalRedirect` can now have redirect codes other than 301 through `redirectCode`.
diff --git a/nixos/doc/manual/release-notes/rl-2411.section.md b/nixos/doc/manual/release-notes/rl-2411.section.md
index dd2db8de5a33..daef530c8993 100644
--- a/nixos/doc/manual/release-notes/rl-2411.section.md
+++ b/nixos/doc/manual/release-notes/rl-2411.section.md
@@ -248,6 +248,9 @@
 
 - `tests.overriding` has its `passthru.tests` restructured as an attribute set instead of a list, making individual tests accessible by their names.
 
+- `services.netbird.tunnels` was renamed to [`services.netbird.clients`](#opt-services.netbird.clients),
+  hardened (using dedicated less-privileged users) and significantly extended.
+
 - `vaultwarden` lost the capability to bind to privileged ports. If you rely on
    this behavior, override the systemd unit to allow `CAP_NET_BIND_SERVICE` in
    your local configuration.
diff --git a/nixos/modules/services/networking/netbird.md b/nixos/modules/services/networking/netbird.md
index e1f6753cbd30..876c27cb0d22 100644
--- a/nixos/modules/services/networking/netbird.md
+++ b/nixos/modules/services/networking/netbird.md
@@ -2,7 +2,7 @@
 
 ## Quickstart {#module-services-netbird-quickstart}
 
-The absolute minimal configuration for the netbird daemon looks like this:
+The absolute minimal configuration for the Netbird client daemon looks like this:
 
 ```nix
 {
@@ -13,52 +13,76 @@ The absolute minimal configuration for the netbird daemon looks like this:
 This will set up a netbird service listening on the port `51820` associated to the
 `wt0` interface.
 
-It is strictly equivalent to setting:
+Which is equivalent to:
 
 ```nix
 {
-  services.netbird.tunnels.wt0.stateDir = "netbird";
+  services.netbird.clients.wt0 = {
+    port = 51820;
+    name = "netbird";
+    interface = "wt0";
+    hardened = false;
+  };
 }
 ```
 
-The `enable` option is mainly kept for backward compatibility, as defining netbird
-tunnels through the `tunnels` option is more expressive.
+This will set up a `netbird.service` listening on the port `51820` associated to the
+`wt0` interface. There will also be `netbird-wt0` binary installed in addition to `netbird`.
+
+see [clients](#opt-services.netbird.clients) option documentation for more details.
 
 ## Multiple connections setup {#module-services-netbird-multiple-connections}
 
-Using the `services.netbird.tunnels` option, it is also possible to define more than
+Using the `services.netbird.clients` option, it is possible to define more than
 one netbird service running at the same time.
 
-The following configuration will start a netbird daemon using the interface `wt1` and
-the port 51830. Its configuration file will then be located at `/var/lib/netbird-wt1/config.json`.
+You must at least define a `port` for the service to listen on, the rest is optional:
 
 ```nix
 {
-  services.netbird.tunnels = {
-    wt1 = {
-      port = 51830;
-    };
-  };
+  services.netbird.clients.wt1.port = 51830;
+  services.netbird.clients.wt2.port = 51831;
 }
 ```
 
-To interact with it, you will need to specify the correct daemon address:
-
-```bash
-netbird --daemon-addr unix:///var/run/netbird-wt1/sock ...
-```
+see [clients](#opt-services.netbird.clients) option documentation for more details.
 
-The address will by default be `unix:///var/run/netbird-<name>`.
+## Exposing services internally on the Netbird network {#module-services-netbird-firewall}
 
-It is also possible to overwrite default options passed to the service, for
-example:
+You can easily expose services exclusively to Netbird network by combining
+[`networking.firewall.interfaces`](#opt-networking.firewall.interfaces) rules
+with [`interface`](#opt-services.netbird.clients._name_.interface) names:
 
 ```nix
 {
-  services.netbird.tunnels.wt1.environment = {
-    NB_DAEMON_ADDR = "unix:///var/run/toto.sock";
+  services.netbird.clients.priv.port = 51819;
+  services.netbird.clients.work.port = 51818;
+  networking.firewall.interfaces = {
+    "${config.services.netbird.clients.priv.interface}" = {
+      allowedUDPPorts = [ 1234 ];
+    };
+    "${config.services.netbird.clients.work.interface}" = {
+      allowedTCPPorts = [ 8080 ];
+    };
   };
 }
 ```
 
-This will set the socket to interact with the netbird service to `/var/run/toto.sock`.
+### Additional customizations {#module-services-netbird-customization}
+
+Each Netbird client service by default:
+
+- runs in a [hardened](#opt-services.netbird.clients._name_.hardened) mode,
+- starts with the system,
+- [opens up a firewall](#opt-services.netbird.clients._name_.openFirewall) for direct (without TURN servers)
+  peer-to-peer communication,
+- can be additionally configured with environment variables,
+- automatically determines whether `netbird-ui-<name>` should be available,
+
+[autoStart](#opt-services.netbird.clients._name_.autoStart) allows you to start the client (an actual systemd service)
+on demand, for example to connect to work-related or otherwise conflicting network only when required.
+See the option description for more information.
+
+[environment](#opt-services.netbird.clients._name_.environment) allows you to pass additional configurations
+through environment variables, but special care needs to be taken for overriding config location and
+daemon address due [hardened](#opt-services.netbird.clients._name_.hardened) option.
diff --git a/nixos/modules/services/networking/netbird.nix b/nixos/modules/services/networking/netbird.nix
index e68c39946fe3..dae0936deb4f 100644
--- a/nixos/modules/services/networking/netbird.nix
+++ b/nixos/modules/services/networking/netbird.nix
@@ -1,72 +1,155 @@
-{
-  config,
-  lib,
-  pkgs,
-  ...
+{ config
+, lib
+, pkgs
+, ...
 }:
 
 let
   inherit (lib)
-    attrNames
+    attrValues
+    concatLists
+    concatStringsSep
+    escapeShellArgs
+    filterAttrs
     getExe
     literalExpression
     maintainers
+    makeBinPath
     mapAttrs'
+    mapAttrsToList
     mkDefault
-    mkEnableOption
     mkIf
     mkMerge
     mkOption
+    mkOptionDefault
     mkPackageOption
+    mkRemovedOptionModule
     nameValuePair
     optional
+    optionalString
+    toShellVars
+    versionAtLeast
     versionOlder
     ;
 
   inherit (lib.types)
     attrsOf
+    bool
+    enum
+    package
     port
     str
     submodule
     ;
 
-  kernel = config.boot.kernelPackages;
+  inherit (config.boot) kernelPackages;
+  inherit (config.boot.kernelPackages) kernel;
 
   cfg = config.services.netbird;
+
+  toClientList = fn: map fn (attrValues cfg.clients);
+  toClientAttrs = fn: mapAttrs' (_: fn) cfg.clients;
+
+  hardenedClients = filterAttrs (_: client: client.hardened) cfg.clients;
+  toHardenedClientList = fn: map fn (attrValues hardenedClients);
+  toHardenedClientAttrs = fn: mapAttrs' (_: fn) hardenedClients;
+
+  nixosConfig = config;
 in
 {
   meta.maintainers = with maintainers; [
     misuzu
+    nazarewk
   ];
   meta.doc = ./netbird.md;
 
+  imports = [
+    (mkRemovedOptionModule [ "services" "netbird" "tunnels" ]
+      "The option `services.netbird.tunnels` has been renamed to `services.netbird.clients`")
+  ];
+
   options.services.netbird = {
-    enable = mkEnableOption "Netbird daemon";
+    enable = mkOption {
+      type = bool;
+      default = false;
+      description = ''
+        Enables backwards compatible Netbird client service.
+
+        This is strictly equivalent to:
+
+        ```nix
+        services.netbird.clients.wt0 = {
+          port = 51820;
+          name = "netbird";
+          interface = "wt0";
+          hardened = false;
+        };
+        ```
+      '';
+    };
     package = mkPackageOption pkgs "netbird" { };
 
-    tunnels = mkOption {
+    ui.enable = mkOption {
+      type = bool;
+      default = config.services.displayManager.sessionPackages != [ ] || config.services.xserver.enable;
+      defaultText = literalExpression ''
+        config.services.displayManager.sessionPackages != [ ] || config.services.xserver.enable
+      '';
+      description = ''
+        Controls presence `netbird-ui` wrappers, defaults to presence of graphical sessions.
+      '';
+    };
+    ui.package = mkPackageOption pkgs "netbird-ui" { };
+
+    clients = mkOption {
       type = attrsOf (
         submodule (
           { name, config, ... }:
+          let client = config; in
           {
             options = {
               port = mkOption {
                 type = port;
-                default = 51820;
+                example = literalExpression "51820";
                 description = ''
-                  Port for the ${name} netbird interface.
+                  Port the Netbird client listens on.
                 '';
               };
 
+              name = mkOption {
+                type = str;
+                default = name;
+                description = ''
+                  Primary name for use (as a suffix) in:
+                  - systemd service name,
+                  - hardened user name and group,
+                  - [systemd `*Directory=`](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#RuntimeDirectory=) names,
+                  - desktop application identification,
+                '';
+              };
+
+              interface = mkOption {
+                type = str;
+                default = "nb-${client.name}";
+                description = ''
+                  Name of the network interface managed by this client.
+                '';
+                apply = iface:
+                  lib.throwIfNot (builtins.stringLength iface <= 15) "Network interface name must be 15 characters or less"
+                  iface;
+              };
+
               environment = mkOption {
                 type = attrsOf str;
                 defaultText = literalExpression ''
                   {
-                    NB_CONFIG = "/var/lib/''${stateDir}/config.json";
-                    NB_LOG_FILE = "console";
-                    NB_WIREGUARD_PORT = builtins.toString port;
-                    NB_INTERFACE_NAME = name;
-                    NB_DAMEON_ADDR = "/var/run/''${stateDir}"
+                    NB_CONFIG = "/var/lib/netbird-''${client.name}/config.json";
+                    NB_DAEMON_ADDR = "unix:///var/run/netbird-''${client.name}/sock";
+                    NB_INTERFACE_NAME = config.interface;
+                    NB_LOG_FILE = mkOptionDefault "console";
+                    NB_LOG_LEVEL = config.logLevel;
+                    NB_SERVICE = "netbird-''${client.name}";
+                    NB_WIREGUARD_PORT = toString config.port;
                   }
                 '';
                 description = ''
@@ -74,97 +157,364 @@ in
                 '';
               };
 
-              stateDir = mkOption {
-                type = str;
-                default = "netbird-${name}";
+              autoStart = mkOption {
+                type = bool;
+                default = true;
+                description = ''
+                  Start the service with the system.
+
+                  As of 2024-02-13 it is not possible to start a Netbird client daemon without immediately
+                  connecting to the network, but it is [planned for a near future](https://github.com/netbirdio/netbird/projects/2#card-91718018).
+                '';
+              };
+
+              openFirewall = mkOption {
+                type = bool;
+                default = true;
+                description = ''
+                  Opens up firewall `port` for communication between Netbird peers directly over LAN or public IP,
+                  without using (internet-hosted) TURN servers as intermediaries.
+                '';
+              };
+
+              hardened = mkOption {
+                type = bool;
+                default = true;
                 description = ''
-                  Directory storing the netbird configuration.
+                  Hardened service:
+                  - runs as a dedicated user with minimal set of permissions (see caveats),
+                  - restricts daemon configuration socket access to dedicated user group
+                    (you can grant access to it with `users.users."<user>".extraGroups = [ "netbird-${client.name}" ]`),
+
+                  Even though the local system resources access is restricted:
+                  - `CAP_NET_RAW`, `CAP_NET_ADMIN` and `CAP_BPF` still give unlimited network manipulation possibilites,
+                  - older kernels don't have `CAP_BPF` and use `CAP_SYS_ADMIN` instead,
+
+                  Known security features that are not (yet) integrated into the module:
+                  - 2024-02-14: `rosenpass` is an experimental feature configurable solely
+                    through `--enable-rosenpass` flag on the `netbird up` command,
+                    see [the docs](https://docs.netbird.io/how-to/enable-post-quantum-cryptography)
+                '';
+              };
+
+              logLevel = mkOption {
+                type = enum [
+                  # logrus loglevels
+                  "panic"
+                  "fatal"
+                  "error"
+                  "warn"
+                  "warning"
+                  "info"
+                  "debug"
+                  "trace"
+                ];
+                default = "info";
+                description = "Log level of the Netbird daemon.";
+              };
+
+              ui.enable = mkOption {
+                type = bool;
+                default = nixosConfig.services.netbird.ui.enable;
+                defaultText = literalExpression ''config.ui.enable'';
+                description = ''
+                  Controls presence of `netbird-ui` wrapper for this Netbird client.
+                '';
+              };
+
+              wrapper = mkOption {
+                type = package;
+                internal = true;
+                default =
+                  let
+                    makeWrapperArgs = concatLists (mapAttrsToList
+                      (key: value: [ "--set-default" key value ])
+                      config.environment
+                    );
+                  in
+                  pkgs.stdenv.mkDerivation {
+                    name = "${cfg.package.name}-wrapper-${client.name}";
+                    meta.mainProgram = "netbird-${client.name}";
+                    nativeBuildInputs = with pkgs; [ makeWrapper ];
+                    phases = [ "installPhase" ];
+                    installPhase = concatStringsSep "\n" [
+                      ''
+                        mkdir -p "$out/bin"
+                        makeWrapper ${lib.getExe cfg.package} "$out/bin/netbird-${client.name}" \
+                          ${escapeShellArgs makeWrapperArgs}
+                      ''
+                      (optionalString cfg.ui.enable ''
+                        # netbird-ui doesn't support envvars
+                        makeWrapper ${lib.getExe cfg.ui.package} "$out/bin/netbird-ui-${client.name}" \
+                          --add-flags '--daemon-addr=${config.environment.NB_DAEMON_ADDR}'
+
+                        mkdir -p "$out/share/applications"
+                        substitute ${cfg.ui.package}/share/applications/netbird.desktop \
+                            "$out/share/applications/netbird-${client.name}.desktop" \
+                          --replace-fail 'Name=Netbird' "Name=Netbird @ netbird-${client.name}" \
+                          --replace-fail '${lib.getExe cfg.ui.package}' "$out/bin/netbird-ui-${client.name}"
+                      '')
+                    ];
+                  };
+              };
+
+              # see https://github.com/netbirdio/netbird/blob/88747e3e0191abc64f1e8c7ecc65e5e50a1527fd/client/internal/config.go#L49-L82
+              config = mkOption {
+                type = (pkgs.formats.json { }).type;
+                defaultText = literalExpression ''
+                  {
+                    DisableAutoConnect = !config.autoStart;
+                    WgIface = config.interface;
+                    WgPort = config.port;
+                  }
+                '';
+                description = ''
+                  Additional configuration that exists before the first start and
+                  later overrides the existing values in `config.json`.
+
+                  It is mostly helpful to manage configuration ignored/not yet implemented
+                  outside of `netbird up` invocation.
+
+                  WARNING: this is not an upstream feature, it could break in the future
+                  (by having lower priority) after upstream implements an equivalent.
+
+                  It is implemented as a `preStart` script which overrides `config.json`
+                  with content of `/etc/netbird-${client.name}/config.d/*.json` files.
+                  This option manages specifically `50-nixos.json` file.
+
+                  Consult [the source code](https://github.com/netbirdio/netbird/blob/88747e3e0191abc64f1e8c7ecc65e5e50a1527fd/client/internal/config.go#L49-L82)
+                  or inspect existing file for a complete list of available configurations.
                 '';
               };
             };
 
-            config.environment = builtins.mapAttrs (_: mkDefault) {
-              NB_CONFIG = "/var/lib/${config.stateDir}/config.json";
-              NB_LOG_FILE = "console";
-              NB_WIREGUARD_PORT = builtins.toString config.port;
-              NB_INTERFACE_NAME = name;
-              NB_DAEMON_ADDR = "unix:///var/run/${config.stateDir}/sock";
+            config.environment = {
+              NB_CONFIG = "/var/lib/netbird-${client.name}/config.json";
+              NB_DAEMON_ADDR = "unix:///var/run/netbird-${client.name}/sock";
+              NB_INTERFACE_NAME = config.interface;
+              NB_LOG_FILE = mkOptionDefault "console";
+              NB_LOG_LEVEL = config.logLevel;
+              NB_SERVICE = "netbird-${client.name}";
+              NB_WIREGUARD_PORT = toString config.port;
+            };
+
+            config.config = {
+              DisableAutoConnect = !config.autoStart;
+              WgIface = config.interface;
+              WgPort = config.port;
             };
           }
         )
       );
       default = { };
       description = ''
-        Attribute set of Netbird tunnels, each one will spawn a daemon listening on ...
+        Attribute set of Netbird client daemons, by default each one will:
+
+        1. be manageable using dedicated tooling:
+          - `netbird-<name>` script,
+          - `Netbird - netbird-<name>` graphical interface when appropriate (see `ui.enable`),
+        2. run as a `netbird-<name>.service`,
+        3. listen for incoming remote connections on the port `51820` (`openFirewall` by default),
+        4. manage the `netbird-<name>` wireguard interface,
+        5. use the `/var/lib/netbird-<name>/config.json` configuration file,
+        6. override `/var/lib/netbird-<name>/config.json` with values from `/etc/netbird-<name>/config.d/*.json`,
+        7. (`hardened`) be locally manageable by `netbird-<name>` system group,
+
+        With following caveats:
+
+        - multiple daemons will interfere with each other's DNS resolution of `netbird.cloud`, but
+          should remain fully operational otherwise.
+          Setting up custom (non-conflicting) DNS zone is currently possible only when self-hosting.
+      '';
+      example = lib.literalExpression ''
+        {
+          services.netbird.clients.wt0.port = 51820;
+          services.netbird.clients.personal.port = 51821;
+          services.netbird.clients.work1.port = 51822;
+        }
       '';
     };
   };
 
   config = mkMerge [
-    (mkIf cfg.enable {
-      # For backwards compatibility
-      services.netbird.tunnels.wt0.stateDir = "netbird";
-    })
+    (mkIf cfg.enable (
+      let name = "wt0"; client = cfg.clients."${name}"; in {
+        services.netbird.clients."${name}" = {
+          port = mkDefault 51820;
+          name = mkDefault "netbird";
+          interface = mkDefault "wt0";
+          hardened = mkDefault false;
+        };
 
-    (mkIf (cfg.tunnels != { }) {
-      boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard;
+        environment.systemPackages = [
+          (lib.hiPrio (pkgs.runCommand "${client.name}-as-default" { } ''
+            mkdir -p "$out/bin"
+            for binary in netbird ${optionalString cfg.ui.enable "netbird-ui"} ; do
+              ln -s "${client.wrapper}/bin/$binary-${client.name}" "$out/bin/$binary"
+            done
+          ''))
+        ];
+      }
+    ))
+    {
+      boot.extraModulePackages = optional
+        (cfg.clients != { } && (versionOlder kernel.version "5.6"))
+        kernelPackages.wireguard;
 
-      environment.systemPackages = [ cfg.package ];
+      environment.systemPackages =
+        toClientList (client: client.wrapper)
+        # omitted due to https://github.com/netbirdio/netbird/issues/1562
+        #++ optional (cfg.clients != { }) cfg.package
+        # omitted due to https://github.com/netbirdio/netbird/issues/1581
+        #++ optional (cfg.clients != { } && cfg.ui.enable) cfg.ui.package
+      ;
 
-      networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels;
+      networking.dhcpcd.denyInterfaces = toClientList (client: client.interface);
+      networking.networkmanager.unmanaged = toClientList (client: "interface-name:${client.interface}");
 
-      systemd.network.networks = mkIf config.networking.useNetworkd (
-        mapAttrs'
-          (
-            name: _:
-            nameValuePair "50-netbird-${name}" {
-              matchConfig = {
-                Name = name;
-              };
-              linkConfig = {
-                Unmanaged = true;
-                ActivationPolicy = "manual";
-              };
-            }
-          )
-          cfg.tunnels
-      );
+      networking.firewall.allowedUDPPorts = concatLists (toClientList (client: optional client.openFirewall client.port));
 
-      systemd.services =
-        mapAttrs'
-          (
-            name:
-            { environment, stateDir, ... }:
-            nameValuePair "netbird-${name}" {
-              description = "A WireGuard-based mesh network that connects your devices into a single private network";
+      systemd.network.networks = mkIf config.networking.useNetworkd (toClientAttrs (client:
+        nameValuePair "50-netbird-${client.interface}" {
+          matchConfig = {
+            Name = client.interface;
+          };
+          linkConfig = {
+            Unmanaged = true;
+            ActivationPolicy = "manual";
+          };
+        }
+      ));
 
-              documentation = [ "https://netbird.io/docs/" ];
+      environment.etc = toClientAttrs (client: nameValuePair "netbird-${client.name}/config.d/50-nixos.json" {
+        text = builtins.toJSON client.config;
+        mode = "0444";
+      });
 
-              after = [ "network.target" ];
-              wantedBy = [ "multi-user.target" ];
+      systemd.services = toClientAttrs (client: nameValuePair "netbird-${client.name}" {
+        description = "A WireGuard-based mesh network that connects your devices into a single private network";
 
-              path = with pkgs; [ openresolv ];
+        documentation = [ "https://netbird.io/docs/" ];
 
-              inherit environment;
+        after = [ "network.target" ];
+        wantedBy = [ "multi-user.target" ];
 
-              serviceConfig = {
-                ExecStart = "${getExe cfg.package} service run";
-                Restart = "always";
-                RuntimeDirectory = stateDir;
-                StateDirectory = stateDir;
-                StateDirectoryMode = "0700";
-                WorkingDirectory = "/var/lib/${stateDir}";
-              };
+        path = optional (!config.services.resolved.enable) pkgs.openresolv;
 
-              unitConfig = {
-                StartLimitInterval = 5;
-                StartLimitBurst = 10;
-              };
+        serviceConfig = {
+          ExecStart = "${getExe client.wrapper} service run";
+          Restart = "always";
+
+          RuntimeDirectory = "netbird-${client.name}";
+          RuntimeDirectoryMode = mkDefault "0755";
+          ConfigurationDirectory = "netbird-${client.name}";
+          StateDirectory = "netbird-${client.name}";
+          StateDirectoryMode = "0700";
+
+          WorkingDirectory = "/var/lib/netbird-${client.name}";
+        };
+
+        unitConfig = {
+          StartLimitInterval = 5;
+          StartLimitBurst = 10;
+        };
+
+        stopIfChanged = false;
+      });
+    }
+    # Hardening section
+    (mkIf (hardenedClients != { }) {
+      users.groups = toHardenedClientAttrs (client: nameValuePair "netbird-${client.name}" { });
+      users.users = toHardenedClientAttrs (client: nameValuePair "netbird-${client.name}" {
+        isSystemUser = true;
+        home = "/var/lib/netbird-${client.name}";
+        group = "netbird-${client.name}";
+      });
+
+      systemd.services = toHardenedClientAttrs (client: nameValuePair "netbird-${client.name}" (mkIf client.hardened {
+        serviceConfig = {
+          RuntimeDirectoryMode = "0750";
+
+          User = "netbird-${client.name}";
+          Group = "netbird-${client.name}";
+
+          # settings implied by DynamicUser=true, without actully using it,
+          # see https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#DynamicUser=
+          RemoveIPC = true;
+          PrivateTmp = true;
+          ProtectSystem = "strict";
+          ProtectHome = "yes";
 
-              stopIfChanged = false;
-            }
-          )
-          cfg.tunnels;
+          AmbientCapabilities = [
+            # see https://man7.org/linux/man-pages/man7/capabilities.7.html
+            # see https://docs.netbird.io/how-to/installation#running-net-bird-in-docker
+            #
+            # seems to work fine without CAP_SYS_ADMIN and CAP_SYS_RESOURCE
+            # CAP_NET_BIND_SERVICE could be added to allow binding on low ports, but is not required,
+            #  see https://github.com/netbirdio/netbird/pull/1513
+
+            # failed creating tunnel interface wt-priv: [operation not permitted
+            "CAP_NET_ADMIN"
+            # failed to pull up wgInterface [wt-priv]: failed to create ipv4 raw socket: socket: operation not permitted
+            "CAP_NET_RAW"
+          ]
+          # required for eBPF filter, used to be subset of CAP_SYS_ADMIN
+          ++ optional (versionAtLeast kernel.version "5.8") "CAP_BPF"
+          ++ optional (versionOlder kernel.version "5.8") "CAP_SYS_ADMIN"
+          ;
+        };
+      }));
+
+      # see https://github.com/systemd/systemd/blob/17f3e91e8107b2b29fe25755651b230bbc81a514/src/resolve/org.freedesktop.resolve1.policy#L43-L43
+      # see all actions used at https://github.com/netbirdio/netbird/blob/13e7198046a0d73a9cd91bf8e063fafb3d41885c/client/internal/dns/systemd_linux.go#L29-L32
+      security.polkit.extraConfig = mkIf config.services.resolved.enable ''
+        // systemd-resolved access for Netbird clients
+        polkit.addRule(function(action, subject) {
+          var actions = [
+            "org.freedesktop.resolve1.revert",
+            "org.freedesktop.resolve1.set-default-route",
+            "org.freedesktop.resolve1.set-dns-servers",
+            "org.freedesktop.resolve1.set-domains",
+          ];
+          var users = ${builtins.toJSON (toHardenedClientList (client: "netbird-${client.name}"))};
+
+          if (actions.indexOf(action.id) >= 0 && users.indexOf(subject.user) >= 0 ) {
+            return polkit.Result.YES;
+          }
+        });
+      '';
     })
+    # migration & temporary fixups section
+    {
+      systemd.services = toClientAttrs (client: nameValuePair "netbird-${client.name}" {
+        preStart = ''
+          set -eEuo pipefail
+          ${optionalString (client.logLevel == "trace" || client.logLevel == "debug") "set -x"}
+
+          PATH="${makeBinPath (with pkgs; [coreutils jq diffutils])}:$PATH"
+          export ${toShellVars client.environment}
+
+          # merge /etc/netbird-${client.name}/config.d' into "$NB_CONFIG"
+          {
+            test -e "$NB_CONFIG" || echo -n '{}' > "$NB_CONFIG"
+
+            # merge config.d with "$NB_CONFIG" into "$NB_CONFIG.new"
+            jq -sS 'reduce .[] as $i ({}; . * $i)' \
+              "$NB_CONFIG" \
+              /etc/netbird-${client.name}/config.d/*.json \
+              > "$NB_CONFIG.new"
+
+            echo "Comparing $NB_CONFIG with $NB_CONFIG.new ..."
+            if ! diff <(jq -S <"$NB_CONFIG") "$NB_CONFIG.new" ; then
+              echo "Updating $NB_CONFIG ..."
+              mv "$NB_CONFIG.new" "$NB_CONFIG"
+            else
+              echo "Files are the same, not doing anything."
+              rm "$NB_CONFIG.new"
+            fi
+          }
+        '';
+      });
+    }
   ];
 }
diff --git a/nixos/tests/netbird.nix b/nixos/tests/netbird.nix
index 7342e8d04a39..063fff6d42f0 100644
--- a/nixos/tests/netbird.nix
+++ b/nixos/tests/netbird.nix
@@ -12,10 +12,32 @@ import ./make-test-python.nix ({ pkgs, lib, ... }:
     };
   };
 
+  # TODO: confirm the whole solution is working end-to-end when netbird server is implemented
   testScript = ''
     start_all()
-    node.wait_for_unit("netbird-wt0.service")
+    node.wait_for_unit("netbird.service")
     node.wait_for_file("/var/run/netbird/sock")
-    node.succeed("netbird status | grep -q 'Daemon status: NeedsLogin'")
+    output = node.succeed("netbird status")
+    # used to print `Daemon status: NeedsLogin`, but not anymore `Management: Disconnected`
+    assert "Disconnected" in output or "NeedsLogin" in output
   '';
+
+  /*
+    `netbird status` used to print `Daemon status: NeedsLogin`
+        https://github.com/netbirdio/netbird/blob/23a14737974e3849fa86408d136cc46db8a885d0/client/cmd/status.go#L154-L164
+    as the first line, but now it is just:
+
+        Daemon version: 0.26.3
+        CLI version: 0.26.3
+        Management: Disconnected
+        Signal: Disconnected
+        Relays: 0/0 Available
+        Nameservers: 0/0 Available
+        FQDN:
+        NetBird IP: N/A
+        Interface type: N/A
+        Quantum resistance: false
+        Routes: -
+        Peers count: 0/0 Connected
+  */
 })
diff --git a/pkgs/tools/networking/netbird/default.nix b/pkgs/tools/networking/netbird/default.nix
index c4bce67ff89d..7a27c2bbef10 100644
--- a/pkgs/tools/networking/netbird/default.nix
+++ b/pkgs/tools/networking/netbird/default.nix
@@ -111,6 +111,6 @@ buildGoModule rec {
     description = "Connect your devices into a single secure private WireGuard®-based mesh network with SSO/MFA and simple access controls";
     license = licenses.bsd3;
     maintainers = with maintainers; [ misuzu vrifox ];
-    mainProgram = "netbird";
+    mainProgram = if ui then "netbird-ui" else "netbird";
   };
 }
