From 063a6d9f24254daed98ff1f4e6b4a101f9e2d5ac Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 21 Nov 2024 18:10:33 +0100 Subject: [PATCH] feat: netbird setup --- config/basic/net.nix | 8 - config/basic/users.nix | 1 + config/services/adguardhome.nix | 1 + config/services/netbird.nix | 19 +- config/services/samba.nix | 24 - hosts/desktopnix/net.nix | 28 +- hosts/elisabeth/default.nix | 1 + hosts/elisabeth/guests.nix | 60 +-- hosts/patricknix/net.nix | 11 +- modules/netbird-client.nix | 219 --------- patches/287236.diff | 789 ++++++++++++++++++++++++++++++ patches/PR/354032.diff | 77 +-- patches/PR/355216.diff | 4 +- users/patrick/wayland/default.nix | 2 +- 14 files changed, 904 insertions(+), 340 deletions(-) delete mode 100644 modules/netbird-client.nix create mode 100644 patches/287236.diff diff --git a/config/basic/net.nix b/config/basic/net.nix index a518fe2..ec38ca7 100644 --- a/config/basic/net.nix +++ b/config/basic/net.nix @@ -1,7 +1,6 @@ { lib, config, - pkgs, ... }: { @@ -34,11 +33,4 @@ ''; }; - services.mullvad-vpn = { - enable = true; - package = pkgs.mullvad-vpn; - }; - environment.persistence."/state".directories = [ - "/etc/mullvad-vpn" - ]; } diff --git a/config/basic/users.nix b/config/basic/users.nix index dd67e2f..5f6efd1 100644 --- a/config/basic/users.nix +++ b/config/basic/users.nix @@ -38,6 +38,7 @@ firefly-iii = uidGid 226; homebox = uidGid 227; signal = uidGid 228; + netbird-main = uidGid 229; paperless = uidGid 315; systemd-oom = uidGid 300; systemd-coredump = uidGid 301; diff --git a/config/services/adguardhome.nix b/config/services/adguardhome.nix index 93c56cf..d586715 100644 --- a/config/services/adguardhome.nix +++ b/config/services/adguardhome.nix @@ -38,6 +38,7 @@ "||adguardhome.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}" "||nc.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}" "||immich.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth config.secrets.secrets.global.net.privateSubnetv4}" + "||smb.${config.secrets.secrets.global.domains.web}^$dnsrewrite=${lib.net.cidr.host config.secrets.secrets.global.net.ips.elisabeth-samba config.secrets.secrets.global.net.privateSubnetv4}" "||fritz.box^$dnsrewrite=${lib.net.cidr.host 1 config.secrets.secrets.global.net.privateSubnetv4}" ]; dhcp.enabled = false; diff --git a/config/services/netbird.nix b/config/services/netbird.nix index 0f619aa..fc1f001 100644 --- a/config/services/netbird.nix +++ b/config/services/netbird.nix @@ -36,6 +36,14 @@ networking.firewall.allowedUDPPorts = [ 3478 ]; # STUN/TURN server services.netbird = { + clients.main = { + port = 51820; + environment = { + NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}"; + NB_ADMIN_URL = "https://netbird.${config.secrets.secrets.global.domains.web}"; + NB_HOSTNAME = "home"; + }; + }; server = { enable = true; domain = "netbird.${config.secrets.secrets.global.domains.web}"; @@ -50,7 +58,10 @@ }; }; - relay.authSecretFile = config.age.secrets.relaySecret.path; + relay = { + authSecretFile = config.age.secrets.relaySecret.path; + settings.NB_EXPOSED_ADDRESS = "rels://netbird.${config.secrets.secrets.global.domains.web}:443"; + }; coturn = { enable = true; @@ -66,6 +77,7 @@ TURNConfig = { Secret._secret = config.age.secrets.coturnSecret.path; }; + Signal.URI = "netbird.${config.secrets.secrets.global.domains.web}:443"; HttpConfig = { # This is not possible # failed validating JWT token sent from peer y1ParZkbzVMQGeU/KMycYl75v90i2O6EwgO1YQZnSFs= with error rpc error: code = Internal desc = unable to fetch account with claims, err: user ID is empty @@ -88,5 +100,10 @@ mode = "440"; user = "netbird"; } + { + directory = "/var/lib/netbird-main"; + mode = "440"; + user = "netbird-main"; + } ]; } diff --git a/config/services/samba.nix b/config/services/samba.nix index 145c51a..c0d3f18 100644 --- a/config/services/samba.nix +++ b/config/services/samba.nix @@ -8,19 +8,6 @@ in openFirewall = true; }; - disabledModules = [ "services/networking/netbird.nix" ]; - - imports = [ ../../modules/netbird-client.nix ]; - services.netbird.tunnels = { - netbird-samba = { - environment = { - NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}"; - NB_HOSTNAME = "samba"; - }; - port = 56789; - }; - }; - age.secrets.resticpasswd = { generator.script = "alnum"; }; @@ -64,7 +51,6 @@ in networking.nftables.firewall.zones.untrusted.interfaces = [ "samba-patrick" - "netbird-samba" ]; services.samba = { @@ -366,16 +352,6 @@ in ]; } )) - (lib.flip lib.mapAttrsToList config.services.netbird.tunnels ( - _: v: { - "/state".directories = [ - { - directory = "/var/lib/${v.stateDir}"; - mode = "0770"; - } - ]; - } - )) ] ); } diff --git a/hosts/desktopnix/net.nix b/hosts/desktopnix/net.nix index edca0e6..7bb24d0 100644 --- a/hosts/desktopnix/net.nix +++ b/hosts/desktopnix/net.nix @@ -1,4 +1,8 @@ -{ config, ... }: +{ + config, + pkgs, + ... +}: { networking = { inherit (config.secrets.secrets.local.networking) hostId; @@ -23,4 +27,26 @@ }; networking.nftables.firewall.zones.untrusted.interfaces = [ "lan01" ]; wireguard.samba-patrick.client.via = "elisabeth-samba"; + services.mullvad-vpn = { + enable = true; + package = pkgs.mullvad-vpn; + }; + environment.persistence."/state".directories = [ + "/etc/mullvad-vpn" + { + directory = "/var/lib/netbird-main"; + owner = "netbird-main"; + } + ]; + services.netbird = { + clients.main = { + port = 51820; + environment = { + NB_MANAGEMENT_URL = "https://netbird.${config.secrets.secrets.global.domains.web}"; + NB_ADMIN_URL = "https://netbird.${config.secrets.secrets.global.domains.web}"; + NB_HOSTNAME = "desktopnix"; + }; + }; + }; + users.users."patrick".extraGroups = [ "netbird-main" ]; } diff --git a/hosts/elisabeth/default.nix b/hosts/elisabeth/default.nix index 1e41cf9..9245ce1 100644 --- a/hosts/elisabeth/default.nix +++ b/hosts/elisabeth/default.nix @@ -27,4 +27,5 @@ }; }; nixpkgs.hostPlatform = "x86_64-linux"; + documentation.enable = false; } diff --git a/hosts/elisabeth/guests.nix b/hosts/elisabeth/guests.nix index ca62bfd..8437783 100644 --- a/hosts/elisabeth/guests.nix +++ b/hosts/elisabeth/guests.nix @@ -24,7 +24,6 @@ let apispotify = "apisptfy"; kanidm = "auth"; oauth2-proxy = "oauth2"; - netbird = "netbird"; actual = "actual"; firefly = "money"; homebox = "homebox"; @@ -44,6 +43,19 @@ let nodes."elisabeth-${hostName}".config.wireguard.elisabeth.ipv4; in { + services.netbird.server.proxy = + let + cfg = nodes.elisabeth-netbird.config.services.netbird.server; + in + { + domain = "netbird.${config.secrets.secrets.global.domains.web}"; + enable = true; + enableNginx = true; + signalAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.signal.port}"; + relayAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.relay.port}"; + managementAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:${toString cfg.management.port}"; + dashboardAddress = "${nodes.elisabeth-netbird.config.wireguard.elisabeth.ipv4}:80"; + }; services.nginx = let blockOf = @@ -129,51 +141,7 @@ in { enable = true; recommendedSetup = true; - upstreams.netbird = { - servers."${ipOf "netbird"}:80" = { }; - extraConfig = '' - zone netbird 64k ; - keepalive 5 ; - ''; - }; - upstreams.netbird-mgmt = { - servers."${ipOf "netbird"}:3000" = { }; - extraConfig = '' - zone netbird 64k ; - keepalive 5 ; - ''; - }; - virtualHosts.${domainOf "netbird"} = { - forceSSL = true; - useACMEHost = "web"; - locations = { - "/" = { - proxyPass = "http://netbird"; - proxyWebsockets = true; - X-Frame-Options = "SAMEORIGIN"; - }; - "/signalexchange.SignalExchange/".extraConfig = '' - grpc_pass grpc://${ipOf "netbird"}:8012; - grpc_read_timeout 1d; - grpc_send_timeout 1d; - grpc_socket_keepalive on; - ''; - - "/api".proxyPass = "http://netbird-mgmt"; - - "/management.ManagementService/".extraConfig = '' - grpc_pass grpc://${ipOf "netbird"}:3000; - grpc_read_timeout 1d; - grpc_send_timeout 1d; - grpc_socket_keepalive on; - ''; - }; - extraConfig = '' - client_max_body_size 500M ; - client_header_timeout 1d; - client_body_timeout 1d; - ''; - }; + virtualHosts."netbird.${config.secrets.secrets.global.domains.web}".useACMEHost = "web"; } (blockOf "vaultwarden" { maxBodySize = "1G"; }) (blockOf "forgejo" { maxBodySize = "1G"; }) diff --git a/hosts/patricknix/net.nix b/hosts/patricknix/net.nix index e30c341..9615851 100644 --- a/hosts/patricknix/net.nix +++ b/hosts/patricknix/net.nix @@ -1,6 +1,9 @@ -{ config, ... }: +{ config, pkgs, ... }: { - environment.persistence."/state".directories = [ "/var/lib/iwd" ]; + environment.persistence."/state".directories = [ + "/var/lib/iwd" + "/etc/mullvad-vpn" + ]; age.secrets.eduroam = { rekeyFile = ./secrets/iwd/eduroam.8021x.age; path = "/var/lib/iwd/eduroam.8021x"; @@ -69,4 +72,8 @@ dhcpV6Config.RouteMetric = 40; }; }; + services.mullvad-vpn = { + enable = true; + package = pkgs.mullvad-vpn; + }; } diff --git a/modules/netbird-client.nix b/modules/netbird-client.nix deleted file mode 100644 index af573d9..0000000 --- a/modules/netbird-client.nix +++ /dev/null @@ -1,219 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -let - inherit (lib) - attrNames - getExe - literalExpression - maintainers - mapAttrs' - mkDefault - mkEnableOption - mkIf - mkMerge - mkOption - mkPackageOption - nameValuePair - optional - versionOlder - ; - - inherit (lib.types) - attrsOf - port - str - submodule - bool - nullOr - path - ; - - kernel = config.boot.kernelPackages; - - cfg = config.services.netbird; -in -{ - meta.maintainers = with maintainers; [ - misuzu - thubrecht - patrickdag - ]; - meta.doc = ./netbird.md; - - options.services.netbird = { - enable = mkEnableOption (lib.mdDoc "Netbird daemon"); - package = mkPackageOption pkgs "netbird" { }; - - tunnels = mkOption { - type = attrsOf ( - submodule ( - { name, config, ... }: - { - options = { - port = mkOption { - type = port; - default = 51820; - description = '' - Port for the ${name} netbird interface. - ''; - }; - - userAccess = mkOption { - type = bool; - description = "Allow unprivileged users access to the control socket"; - default = false; - }; - - environmentFile = mkOption { - type = nullOr path; - default = null; - description = "An additional environment file for this service."; - }; - 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}" - } - ''; - description = '' - Environment for the netbird service, used to pass configuration options. - ''; - }; - - stateDir = mkOption { - type = str; - default = "netbird-${name}"; - description = '' - Directory storing the netbird configuration. - ''; - }; - }; - - 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"; - }; - } - ) - ); - default = { }; - description = '' - Attribute set of Netbird tunnels, each one will spawn a daemon listening on ... - ''; - }; - }; - - config = mkMerge [ - (mkIf cfg.enable { - # For backwards compatibility - services.netbird.tunnels.wt0.stateDir = "netbird"; - }) - - (mkIf (cfg.tunnels != { }) { - boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard; - - environment.systemPackages = [ cfg.package ]; - - networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels; - - systemd.network.networks = mkIf config.networking.useNetworkd ( - mapAttrs' ( - name: _: - nameValuePair "50-netbird-${name}" { - matchConfig = { - Name = name; - }; - linkConfig = { - Unmanaged = true; - ActivationPolicy = "manual"; - }; - } - ) cfg.tunnels - ); - - systemd.services = mapAttrs' ( - name: - { - environment, - stateDir, - environmentFile, - userAccess, - ... - }: - nameValuePair "netbird-${name}" { - description = "A WireGuard-based mesh network that connects your devices into a single private network"; - - documentation = [ "https://netbird.io/docs/" ]; - - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - - path = with pkgs; [ openresolv ]; - - inherit environment; - - serviceConfig = { - EnvironmentFile = mkIf (environmentFile != null) environmentFile; - ExecStart = "${getExe cfg.package} service run"; - Restart = "always"; - RuntimeDirectory = stateDir; - StateDirectory = stateDir; - StateDirectoryMode = "0700"; - WorkingDirectory = "/var/lib/${stateDir}"; - RuntimeDirectoryMode = if userAccess then "0755" else "0750"; - - # hardening - LockPersonality = true; - MemoryDenyWriteExecute = true; - NoNewPrivileges = true; - PrivateMounts = true; - PrivateTmp = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectHome = true; - ProtectHostname = true; - ProtectKernelLogs = true; - ProtectKernelModules = false; # needed to load wg module for kernel-mode WireGuard - ProtectKernelTunables = false; - ProtectSystem = true; - RemoveIPC = true; - RestrictNamespaces = true; - RestrictRealtime = true; - RestrictSUIDSGID = true; - - # Hardening - #CapabilityBoundingSet = ""; - #PrivateUsers = true; - #ProtectProc = "invisible"; - #ProcSubset = "pid"; - #RestrictAddressFamilies = [ - # "AF_INET" - # "AF_INET6" - # "AF_NETLINK" - #]; - #SystemCallArchitectures = "native"; - #SystemCallFilter = [ - # "@system-service" - # "@pkey" - #]; - UMask = "0077"; - }; - - stopIfChanged = false; - } - ) cfg.tunnels; - }) - ]; -} diff --git a/patches/287236.diff b/patches/287236.diff new file mode 100644 index 0000000..c6d4cbe --- /dev/null +++ b/patches/287236.diff @@ -0,0 +1,789 @@ +diff --git a/nixos/modules/services/networking/netbird.md b/nixos/modules/services/networking/netbird.md +index e1f6753cbd30c..876c27cb0d22e 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-`. ++## 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-` 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 d39c373dbc94c..c9a2251437c6a 100644 +--- a/nixos/modules/services/networking/netbird.nix ++++ b/nixos/modules/services/networking/netbird.nix +@@ -7,64 +7,179 @@ + + 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 ++ optionalAttrs ++ optionalString ++ toShellVars ++ versionAtLeast + versionOlder + ; + + inherit (lib.types) + attrsOf ++ bool ++ enum ++ nullOr ++ 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; [ ]; ++ meta.maintainers = with maintainers; [ ++ 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 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, ++ ''; ++ }; ++ ++ dns-resolver.address = mkOption { ++ type = nullOr str; ++ default = null; ++ example = "127.0.0.123"; + description = '' +- Port for the ${name} netbird interface. ++ An explicit address that Netbird will serve `*.netbird.cloud.` (usually) entries on. ++ ++ Netbird serves DNS on it's own (dynamic) client address by default. + ''; + }; + ++ dns-resolver.port = mkOption { ++ type = port; ++ default = 53; ++ description = '' ++ A port to serve DNS entries on when `dns-resolver.address` is enabled. ++ ''; ++ }; ++ ++ 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 = client.interface; ++ NB_LOG_FILE = mkOptionDefault "console"; ++ NB_LOG_LEVEL = client.logLevel; ++ NB_SERVICE = "netbird-''${client.name}"; ++ NB_WIREGUARD_PORT = toString client.port; ++ } // optionalAttrs (client.dns-resolver.address != null) { ++ NB_DNS_RESOLVER_ADDRESS = "''${client.dns-resolver.address}:''${builtins.toString client.dns-resolver.port}"; + } + ''; + description = '' +@@ -72,97 +187,416 @@ in + ''; + }; + +- stateDir = mkOption { +- type = str; +- default = "netbird-${name}"; ++ autoStart = mkOption { ++ type = bool; ++ default = true; + description = '' +- 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 ++ connecting to the network, but it is [planned for a near future](https://github.com/netbirdio/netbird/projects/2#card-91718018). + ''; + }; +- }; + +- 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"; ++ 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 = '' ++ 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."".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 ''client.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 ++ ]) client.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=${client.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 = !client.autoStart; ++ WgIface = client.interface; ++ WgPort = client.port; ++ } // optionalAttrs (client.dns-resolver.address != null) { ++ CustomDNSAddress = "''${client.dns-resolver.address}:''${builtins.toString client.dns-resolver.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 = ++ { ++ NB_CONFIG = "/var/lib/netbird-${client.name}/config.json"; ++ NB_DAEMON_ADDR = "unix:///var/run/netbird-${client.name}/sock"; ++ NB_INTERFACE_NAME = client.interface; ++ NB_LOG_FILE = mkOptionDefault "console"; ++ NB_LOG_LEVEL = client.logLevel; ++ NB_SERVICE = "netbird-${client.name}"; ++ NB_WIREGUARD_PORT = toString client.port; ++ } ++ // optionalAttrs (client.dns-resolver.address != null) { ++ NB_DNS_RESOLVER_ADDRESS = "${client.dns-resolver.address}:${builtins.toString client.dns-resolver.port}"; ++ }; ++ ++ config.config = ++ { ++ DisableAutoConnect = !client.autoStart; ++ WgIface = client.interface; ++ WgPort = client.port; ++ } ++ // optionalAttrs (client.dns-resolver.address != null) { ++ CustomDNSAddress = "${client.dns-resolver.address}:${builtins.toString client.dns-resolver.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-` script, ++ - `Netbird - netbird-` graphical interface when appropriate (see `ui.enable`), ++ 2. run as a `netbird-.service`, ++ 3. listen for incoming remote connections on the port `51820` (`openFirewall` by default), ++ 4. manage the `netbird-` wireguard interface, ++ 5. use the `/var/lib/netbird-/config.json` configuration file, ++ 6. override `/var/lib/netbird-/config.json` with values from `/etc/netbird-/config.d/*.json`, ++ 7. (`hardened`) be locally manageable by `netbird-` 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; ++ }; ++ ++ 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; + +- (mkIf (cfg.tunnels != { }) { +- boot.extraModulePackages = optional (versionOlder kernel.kernel.version "5.6") kernel.wireguard; ++ 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 ++ ; + +- environment.systemPackages = [ cfg.package ]; ++ networking.dhcpcd.denyInterfaces = toClientList (client: client.interface); ++ networking.networkmanager.unmanaged = toClientList (client: "interface-name:${client.interface}"); + +- networking.dhcpcd.denyInterfaces = attrNames cfg.tunnels; ++ networking.firewall.allowedUDPPorts = concatLists ( ++ toClientList (client: optional client.openFirewall client.port) ++ ); + + systemd.network.networks = mkIf config.networking.useNetworkd ( +- mapAttrs' +- ( +- name: _: +- nameValuePair "50-netbird-${name}" { +- matchConfig = { +- Name = name; +- }; +- linkConfig = { +- Unmanaged = true; +- ActivationPolicy = "manual"; +- }; +- } +- ) +- cfg.tunnels ++ toClientAttrs ( ++ client: ++ nameValuePair "50-netbird-${client.interface}" { ++ matchConfig = { ++ Name = client.interface; ++ }; ++ linkConfig = { ++ Unmanaged = true; ++ ActivationPolicy = "manual"; ++ }; ++ } ++ ) + ); + +- systemd.services = +- mapAttrs' +- ( +- name: +- { environment, stateDir, ... }: +- nameValuePair "netbird-${name}" { +- description = "A WireGuard-based mesh network that connects your devices into a single private network"; ++ environment.etc = toClientAttrs ( ++ client: ++ nameValuePair "netbird-${client.name}/config.d/50-nixos.json" { ++ text = builtins.toJSON client.config; ++ mode = "0444"; ++ } ++ ); + +- documentation = [ "https://netbird.io/docs/" ]; ++ systemd.services = toClientAttrs ( ++ client: ++ nameValuePair "netbird-${client.name}" { ++ description = "A WireGuard-based mesh network that connects your devices into a single private network"; + +- after = [ "network.target" ]; +- wantedBy = [ "multi-user.target" ]; ++ documentation = [ "https://netbird.io/docs/" ]; + +- path = with pkgs; [ openresolv ]; ++ after = [ "network.target" ]; ++ wantedBy = [ "multi-user.target" ]; + +- inherit environment; ++ path = optional (!config.services.resolved.enable) pkgs.openresolv; + +- serviceConfig = { +- ExecStart = "${getExe cfg.package} service run"; +- Restart = "always"; +- RuntimeDirectory = stateDir; +- StateDirectory = stateDir; +- StateDirectoryMode = "0700"; +- WorkingDirectory = "/var/lib/${stateDir}"; +- }; ++ serviceConfig = { ++ ExecStart = "${getExe client.wrapper} service run"; ++ Restart = "always"; + +- unitConfig = { +- StartLimitInterval = 5; +- StartLimitBurst = 10; +- }; ++ RuntimeDirectory = "netbird-${client.name}"; ++ RuntimeDirectoryMode = mkDefault "0755"; ++ ConfigurationDirectory = "netbird-${client.name}"; ++ StateDirectory = "netbird-${client.name}"; ++ StateDirectoryMode = "0700"; + +- stopIfChanged = false; +- } +- ) +- cfg.tunnels; ++ 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"; ++ ++ 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" ++ ++ optional ( ++ client.dns-resolver.address != null && client.dns-resolver.port < 1024 ++ ) "CAP_NET_BIND_SERVICE"; ++ }; ++ } ++ ) ++ ); ++ ++ # 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/patches/PR/354032.diff b/patches/PR/354032.diff index e0c7cf5..c67597a 100644 --- a/patches/PR/354032.diff +++ b/patches/PR/354032.diff @@ -12,7 +12,7 @@ index 788b724231be3..c8f6836f0af93 100644 domain = mkOption { type = str; diff --git a/nixos/modules/services/networking/netbird/management.nix b/nixos/modules/services/networking/netbird/management.nix -index f4b5bbf643239..da5b851c3fb3e 100644 +index f4b5bbf643239..bf95ea65e5fa3 100644 --- a/nixos/modules/services/networking/netbird/management.nix +++ b/nixos/modules/services/networking/netbird/management.nix @@ -38,7 +38,7 @@ let @@ -33,7 +33,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 Username = "netbird"; Password = "netbird"; } -@@ -58,10 +58,15 @@ let +@@ -58,10 +58,14 @@ let Secret = "not-secure-secret"; TimeBasedCredentials = false; }; @@ -46,11 +46,10 @@ index f4b5bbf643239..da5b851c3fb3e 100644 Signal = { Proto = "https"; - URI = "${cfg.domain}:443"; -+ URI = "localhost:${builtins.toString cfg.signal.port}"; Username = ""; Password = null; }; -@@ -79,9 +84,9 @@ let +@@ -79,9 +83,9 @@ let }; HttpConfig = { @@ -62,7 +61,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 }; IdpManagerConfig = { -@@ -128,18 +133,18 @@ let +@@ -128,18 +132,18 @@ let }; }; @@ -84,7 +83,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 domain = mkOption { type = str; -@@ -196,6 +201,12 @@ in +@@ -196,6 +200,12 @@ in description = "Internal port of the management server."; }; @@ -97,7 +96,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 extraOptions = mkOption { type = listOf str; default = [ ]; -@@ -218,7 +229,7 @@ in +@@ -218,7 +228,7 @@ in Stuns = [ { Proto = "udp"; @@ -106,7 +105,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 Username = ""; Password = null; } -@@ -228,7 +239,7 @@ in +@@ -228,7 +238,7 @@ in Turns = [ { Proto = "udp"; @@ -115,7 +114,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 Username = "netbird"; Password = "netbird"; } -@@ -241,7 +252,7 @@ in +@@ -241,7 +251,7 @@ in Signal = { Proto = "https"; @@ -124,7 +123,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 Username = ""; Password = null; }; -@@ -257,9 +268,9 @@ in +@@ -257,9 +267,9 @@ in StoreConfig = { Engine = "sqlite"; }; HttpConfig = { @@ -136,7 +135,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 }; IdpManagerConfig = { -@@ -334,11 +345,9 @@ in +@@ -334,11 +344,9 @@ in default = "INFO"; description = "Log level of the netbird services."; }; @@ -149,7 +148,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 warnings = concatMap ( -@@ -373,7 +382,7 @@ in +@@ -373,7 +381,7 @@ in serviceConfig = { ExecStart = escapeSystemdExecArgs ( [ @@ -158,7 +157,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 "management" # Config file "--config" -@@ -383,25 +392,28 @@ in +@@ -383,25 +391,28 @@ in "${stateDir}/data" # DNS domain "--dns-domain" @@ -194,7 +193,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 ); Restart = "always"; RuntimeDirectory = "netbird-mgmt"; -@@ -434,27 +446,5 @@ in +@@ -434,27 +445,5 @@ in stopIfChanged = false; }; @@ -224,7 +223,7 @@ index f4b5bbf643239..da5b851c3fb3e 100644 } diff --git a/nixos/modules/services/networking/netbird/proxy.nix b/nixos/modules/services/networking/netbird/proxy.nix new file mode 100644 -index 0000000000000..998ddbad212cf +index 0000000000000..440f3c1d710a3 --- /dev/null +++ b/nixos/modules/services/networking/netbird/proxy.nix @@ -0,0 +1,104 @@ @@ -234,6 +233,7 @@ index 0000000000000..998ddbad212cf + mkEnableOption + mkIf + mkOption ++ mkDefault + ; + inherit (lib.types) str; + cfg = config.services.netbird.server.proxy; @@ -274,10 +274,19 @@ index 0000000000000..998ddbad212cf + enable = true; + + virtualHosts.${cfg.domain} = { ++ forceSSL = mkDefault true; ++ extraConfig = '' ++ proxy_set_header X-Real-IP $remote_addr; ++ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ++ proxy_set_header X-Scheme $scheme; ++ proxy_set_header X-Forwarded-Proto https; ++ proxy_set_header X-Forwarded-Host $host; ++ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ++ ''; + locations = { + "/" = { + proxyPass = "http://${cfg.dashboardAddress}"; -+ proxyWebSockets = true; ++ proxyWebsockets = true; + }; + "/api".proxyPass = "http://${cfg.managementAddress}"; + @@ -286,8 +295,6 @@ index 0000000000000..998ddbad212cf + # see https://stackoverflow.com/a/67805465 + client_body_timeout 1d; + -+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -+ + grpc_pass grpc://${cfg.managementAddress}; + grpc_read_timeout 1d; + grpc_send_timeout 1d; @@ -299,8 +306,6 @@ index 0000000000000..998ddbad212cf + # see https://stackoverflow.com/a/67805465 + client_body_timeout 1d; + -+ grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -+ + grpc_pass grpc://${cfg.signalAddress}; + grpc_read_timeout 1d; + grpc_send_timeout 1d; @@ -314,12 +319,6 @@ index 0000000000000..998ddbad212cf + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + -+ # Forward headers -+ proxy_set_header Host $http_host; -+ proxy_set_header X-Real-IP $remote_addr; -+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -+ proxy_set_header X-Forwarded-Proto $scheme; -+ + # Timeout settings + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; @@ -334,10 +333,10 @@ index 0000000000000..998ddbad212cf +} diff --git a/nixos/modules/services/networking/netbird/relay.nix b/nixos/modules/services/networking/netbird/relay.nix new file mode 100644 -index 0000000000000..38af7fb1b2865 +index 0000000000000..01c4186505b0c --- /dev/null +++ b/nixos/modules/services/networking/netbird/relay.nix -@@ -0,0 +1,124 @@ +@@ -0,0 +1,123 @@ +{ + config, + lib, @@ -419,7 +418,6 @@ index 0000000000000..38af7fb1b2865 + config = mkIf cfg.enable { + services.netbird.server.relay.settings = { + NB_LISTEN_ADDRESS = mkDefault ":${builtins.toString cfg.port}"; -+ NB_EXPOSED_ADDRESS = mkDefault "rel://${cfg.domain}:${builtins.toString cfg.port}"; + NB_METRICS_PORT = mkDefault "9092"; # Upstream default is 9090 but this would clash for nixos where all services run on the same host + }; + systemd.services.netbird-relay = { @@ -428,7 +426,7 @@ index 0000000000000..38af7fb1b2865 + environment = cfg.settings; + + script = '' -+ export NB_AUTH_SECRET="(<${cfg.authSecretFile})" ++ export NB_AUTH_SECRET="$(<${cfg.authSecretFile})" + ${getExe' cfg.package "netbird-relay"} + ''; + serviceConfig = { @@ -463,7 +461,7 @@ index 0000000000000..38af7fb1b2865 + }; +} diff --git a/nixos/modules/services/networking/netbird/server.md b/nixos/modules/services/networking/netbird/server.md -index 3649e97b379e5..d5c137f4fff98 100644 +index 3649e97b379e5..ffda72c0626a4 100644 --- a/nixos/modules/services/networking/netbird/server.md +++ b/nixos/modules/services/networking/netbird/server.md @@ -4,9 +4,10 @@ NetBird is a VPN built on top of WireGuard® making it easy to create secure pri @@ -491,7 +489,7 @@ index 3649e97b379e5..d5c137f4fff98 100644 coturn = { enable = true; -@@ -24,19 +28,16 @@ services.netbird.server = { +@@ -24,19 +28,17 @@ services.netbird.server = { management = { oidcConfigEndpoint = "https://sso.example.selfhosted/oauth2/openid/netbird/.well-known/openid-configuration"; @@ -508,6 +506,7 @@ index 3649e97b379e5..d5c137f4fff98 100644 - ]; - }; - }; ++ settings.Signal.URI = "publicly reachable signal endpoint"; }; }; ``` @@ -522,7 +521,7 @@ index 3649e97b379e5..d5c137f4fff98 100644 + +``` diff --git a/nixos/modules/services/networking/netbird/server.nix b/nixos/modules/services/networking/netbird/server.nix -index 1725374d03c6b..5d02a4017328b 100644 +index 1725374d03c6b..b481770071b82 100644 --- a/nixos/modules/services/networking/netbird/server.nix +++ b/nixos/modules/services/networking/netbird/server.nix @@ -16,7 +16,7 @@ in @@ -558,7 +557,7 @@ index 1725374d03c6b..5d02a4017328b 100644 managementServer = "https://${cfg.domain}"; }; -@@ -53,7 +52,6 @@ in +@@ -53,31 +52,35 @@ in { domain = mkDefault cfg.domain; enable = mkDefault cfg.enable; @@ -566,7 +565,13 @@ index 1725374d03c6b..5d02a4017328b 100644 } // (optionalAttrs cfg.coturn.enable rec { turnDomain = cfg.domain; -@@ -66,18 +64,22 @@ in + turnPort = config.services.coturn.tls-listening-port; + # We cannot merge a list of attrsets so we have to redefine the whole list + settings = { ++ Signal.URI = mkDefault "${cfg.domain}:${builtins.toString cfg.signal.port}"; + TURNConfig.Turns = mkDefault [ + { + Proto = "udp"; URI = "turn:${turnDomain}:${builtins.toString turnPort}"; Username = "netbird"; Password = @@ -589,7 +594,7 @@ index 1725374d03c6b..5d02a4017328b 100644 + }; + + relay = { -+ settings.NB_EXPOSED_ADDRESS = "rel://${cfg.domain}/${builtins.toString cfg.relay.port}"; ++ settings.NB_EXPOSED_ADDRESS = mkDefault "rel://${cfg.domain}/${builtins.toString cfg.relay.port}"; + enable = mkDefault cfg.enable; }; diff --git a/patches/PR/355216.diff b/patches/PR/355216.diff index b9f0376..1f52f80 100644 --- a/patches/PR/355216.diff +++ b/patches/PR/355216.diff @@ -1,5 +1,5 @@ diff --git a/nixos/modules/services/security/kanidm.nix b/nixos/modules/services/security/kanidm.nix -index a368b6eee2a6e..114400de434a3 100644 +index a368b6eee2a6e..3f90ad99b7700 100644 --- a/nixos/modules/services/security/kanidm.nix +++ b/nixos/modules/services/security/kanidm.nix @@ -502,13 +502,13 @@ in @@ -7,7 +7,7 @@ index a368b6eee2a6e..114400de434a3 100644 originUrl = mkOption { - description = "The origin URL of the service. OAuth2 redirects will only be allowed to sites under this origin. Must end with a slash."; -+ description = "The redirect URL of the service. By default this needs to exactly match the OAuth2 redirect target. When disabling strict-redirect-uri kanidm will only match by origin."; ++ description = "The redirect URL of the service. These need to exactly match the OAuth2 redirect target"; type = let - originStrType = types.strMatching ".*://.*/$"; diff --git a/users/patrick/wayland/default.nix b/users/patrick/wayland/default.nix index 6ba1e9c..f90e829 100644 --- a/users/patrick/wayland/default.nix +++ b/users/patrick/wayland/default.nix @@ -52,7 +52,7 @@ # Autostart compositor if on tty1 (once, don't restart after logout) hm.programs.zsh.initExtra = lib.mkOrder 9999 '' if uwsm check may-start ; then - exec systemd-cat -t uwsm_start uwsm start -S -F Hyperland + exec systemd-cat -t uwsm_start uwsm start -S -F Hyprland fi ''; }