From 13ab9514f8b39a568e5e17c3c55011c1907a92a2 Mon Sep 17 00:00:00 2001 From: oddlama Date: Tue, 18 Feb 2025 15:31:52 +0100 Subject: [PATCH] chore: bye netbird --- README.md | 2 +- config/users.nix | 2 +- hosts/sentinel/coturn.nix | 85 ----- hosts/sentinel/default.nix | 1 - hosts/ward/default.nix | 15 - hosts/ward/guests/home-gateway.nix | 34 -- hosts/ward/guests/kanidm.nix | 17 +- hosts/ward/guests/netbird.nix | 160 -------- hosts/ward/secrets/netbird/host.pub | 1 - modules/default.nix | 5 - modules/netbird-client.nix | 546 ---------------------------- secrets/global.nix.age | Bin 3449 -> 3532 bytes 12 files changed, 10 insertions(+), 858 deletions(-) delete mode 100644 hosts/sentinel/coturn.nix delete mode 100644 hosts/ward/guests/home-gateway.nix delete mode 100644 hosts/ward/guests/netbird.nix delete mode 100644 hosts/ward/secrets/netbird/host.pub delete mode 100644 modules/netbird-client.nix diff --git a/README.md b/README.md index 578bef5..230774c 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ I've included the major components in the lists below. 📄 Documents | Paperless | [Link](./hosts/sire/guests/paperless.nix) | Document management system. With per-user Samba share integration (consume & archive) 🗓️ CalDAV/CardDAV | Radicale | [Link](./hosts/ward/guests/radicale.nix) | Contacts, Calender and Tasks synchronization 📁 NAS | Samba | [Link](./hosts/sire/guests/samba.nix) | Network attached storage. Cross-integration with paperless -🌐 VPN | Netbird | [Link](./hosts/ward/guests/netbird.nix) | Internal network gateway and wireguard VPN server with dynamic peer configuration and SSO authentication. +🌐 VPN | Firezone | [Link](./hosts/ward/guests/firezone.nix) | Internal network gateway and wireguard VPN server with dynamic peer configuration and SSO authentication. 🏠 Home Automation | Home Assistant | [Link](./hosts/zackbiene/home-assistant.nix) | Automation with Home Assistant and many related services 📧 Mailserver | Stalwart | [Link](./hosts/envoy/stalwart-mail.nix) | Modern mail server setup with custom self-service alias management including Bitwarden integration 🧱 Minecraft | PaperMC | [Link](./hosts/sire/guests/minecraft.nix) | Minecraft game server. Autostart on connect, systemd service with background console, automatic backups diff --git a/config/users.nix b/config/users.nix index 8ffd1cd..de872ee 100644 --- a/config/users.nix +++ b/config/users.nix @@ -35,7 +35,7 @@ maddy = uidGid 976; minecraft = uidGid 975; stalwart-mail = uidGid 974; - netbird-home = uidGid 973; + # 973 gamemode = uidGid 972; plausible = uidGid 971; actual = uidGid 970; diff --git a/hosts/sentinel/coturn.nix b/hosts/sentinel/coturn.nix deleted file mode 100644 index 50ea114..0000000 --- a/hosts/sentinel/coturn.nix +++ /dev/null @@ -1,85 +0,0 @@ -{ - config, - globals, - lib, - pkgs, - ... -}: -let - inherit (lib) - getExe - mkAfter - mkForce - ; - - hostDomain = globals.domains.me; - coturnDomain = "coturn.${hostDomain}"; -in -{ - age.secrets.coturn-password-netbird = { - generator.script = "alnum"; - group = "turnserver"; - mode = "440"; - }; - - networking.firewall.allowedUDPPorts = [ - config.services.coturn.listening-port - config.services.coturn.alt-listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-tls-listening-port - ]; - networking.firewall.allowedTCPPorts = [ - config.services.coturn.listening-port - config.services.coturn.alt-listening-port - config.services.coturn.tls-listening-port - config.services.coturn.alt-tls-listening-port - ]; - networking.firewall.allowedUDPPortRanges = [ - { - from = config.services.coturn.min-port; - to = config.services.coturn.max-port; - } - ]; - globals.services.coturn.domain = coturnDomain; - - services.coturn = { - enable = true; - - realm = coturnDomain; - lt-cred-mech = true; - no-cli = true; - - extraConfig = '' - fingerprint - user=netbird:@password@ - no-software-attribute - ''; - - cert = "@cert@"; - pkey = "@pkey@"; - }; - - systemd.services.coturn = - let - certsDir = config.security.acme.certs.${hostDomain}.directory; - in - { - preStart = mkAfter '' - ${getExe pkgs.replace-secret} @password@ ${config.age.secrets.coturn-password-netbird.path} /run/coturn/turnserver.cfg - ${getExe pkgs.replace-secret} @cert@ <(echo "$CREDENTIALS_DIRECTORY/cert.pem") /run/coturn/turnserver.cfg - ${getExe pkgs.replace-secret} @pkey@ <(echo "$CREDENTIALS_DIRECTORY/pkey.pem") /run/coturn/turnserver.cfg - ''; - serviceConfig = { - LoadCredential = [ - "cert.pem:${certsDir}/fullchain.pem" - "pkey.pem:${certsDir}/key.pem" - ]; - Restart = mkForce "always"; - RestartSec = "60"; # Retry every minute - }; - }; - - security.acme.certs.${hostDomain}.postRun = '' - systemctl restart coturn.service - ''; -} diff --git a/hosts/sentinel/default.nix b/hosts/sentinel/default.nix index 810ae96..647e16d 100644 --- a/hosts/sentinel/default.nix +++ b/hosts/sentinel/default.nix @@ -11,7 +11,6 @@ ./acme.nix ./blog.nix - ./coturn.nix ./fs.nix ./net.nix ./oauth2.nix diff --git a/hosts/ward/default.nix b/hosts/ward/default.nix index 09e5af2..30f147f 100644 --- a/hosts/ward/default.nix +++ b/hosts/ward/default.nix @@ -100,27 +100,12 @@ }; }; }; - - # deadnix: skip - mkContainer = guestName: { - ${guestName} = mkGuest guestName // { - backend = "container"; - container.macvlan = "lan"; - extraSpecialArgs = { - inherit (inputs.self) nodes globals; - inherit (inputs.self.pkgs.x86_64-linux) lib; - inherit inputs minimal; - }; - }; - }; in lib.mkIf (!minimal) ( { } // mkMicrovm "adguardhome" // mkMicrovm "forgejo" - // mkMicrovm "home-gateway" // mkMicrovm "kanidm" - // mkMicrovm "netbird" // mkMicrovm "radicale" // mkMicrovm "vaultwarden" // mkMicrovm "web-proxy" diff --git a/hosts/ward/guests/home-gateway.nix b/hosts/ward/guests/home-gateway.nix deleted file mode 100644 index 005bfd9..0000000 --- a/hosts/ward/guests/home-gateway.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ globals, ... }: -{ - # Forwarding required to masquerade netbird network - boot.kernel.sysctl."net.ipv4.ip_forward" = 1; - - wireguard.proxy-home.client.via = "ward"; - - networking.nftables.chains.forward.from-netbird = { - after = [ "conntrack" ]; - rules = [ - "iifname wt-home oifname lan accept" - ]; - }; - - environment.persistence."/persist".directories = [ - { - directory = "/var/lib/netbird-home"; - mode = "0700"; - } - ]; - - services.netbird.clients.home = { - port = 51820; - name = "netbird-home"; - interface = "wt-home"; - openFirewall = true; - config.ServerSSHAllowed = false; - environment = rec { - NB_MANAGEMENT_URL = "https://${globals.services.netbird.domain}"; - NB_ADMIN_URL = NB_MANAGEMENT_URL; - NB_HOSTNAME = "home-gateway"; - }; - }; -} diff --git a/hosts/ward/guests/kanidm.nix b/hosts/ward/guests/kanidm.nix index 993de8e..8b2606c 100644 --- a/hosts/ward/guests/kanidm.nix +++ b/hosts/ward/guests/kanidm.nix @@ -135,17 +135,16 @@ in ]; }; - # Netbird - groups."netbird.access" = { }; - systems.oauth2.netbird = { + # Firezone + groups."firezone.access" = { }; + systems.oauth2.firezone = { public = true; - displayName = "Netbird"; - originUrl = "https://${globals.services.netbird.domain}/"; - originLanding = "https://${globals.services.netbird.domain}/"; + displayName = "Firezone VPN"; + # FIXME: change + originUrl = "https://dummy.example.org/"; + originLanding = "https://dummy.example.org/"; preferShortUsername = true; - enableLocalhostRedirects = true; - enableLegacyCrypto = true; - scopeMaps."netbird.access" = [ + scopeMaps."firezone.access" = [ "openid" "email" "profile" diff --git a/hosts/ward/guests/netbird.nix b/hosts/ward/guests/netbird.nix deleted file mode 100644 index 755b406..0000000 --- a/hosts/ward/guests/netbird.nix +++ /dev/null @@ -1,160 +0,0 @@ -{ - config, - globals, - lib, - nodes, - ... -}: -let - sentinelCfg = nodes.sentinel.config; - netbirdDomain = "netbird.${globals.domains.me}"; -in -{ - wireguard.proxy-sentinel = { - client.via = "sentinel"; - firewallRuleForNode.sentinel.allowedTCPPorts = [ - config.services.netbird.server.management.port - config.services.netbird.server.signal.port - ]; - }; - - # Mirror the original coturn password - age.secrets.coturn-password-netbird = { - inherit (sentinelCfg.age.secrets.coturn-password-netbird) rekeyFile; - }; - - age.secrets.coturn-secret = { - generator.script = "alnum"; - }; - - age.secrets.netbird-data-store-encryption-key = { - generator.script = - { pkgs, ... }: - '' - ${lib.getExe pkgs.openssl} rand -base64 32 - ''; - }; - - environment.persistence."/persist".directories = [ - { - directory = "/var/lib/netbird-mgmt"; - mode = "640"; - user = "netbird"; - group = "netbird"; - } - ]; - - services.netbird = { - server = { - enable = true; - domain = netbirdDomain; - - dashboard.settings.AUTH_AUTHORITY = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird"; - - management = { - singleAccountModeDomain = "internal.${globals.domains.me}"; - dnsDomain = "internal.${globals.domains.me}"; - disableAnonymousMetrics = true; - oidcConfigEndpoint = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird/.well-known/openid-configuration"; - turnDomain = globals.services.coturn.domain; - turnPort = sentinelCfg.services.coturn.tls-listening-port; - settings = { - HttpConfig = { - # Audience must be set here, otherwise the grpc server will not initialize the jwt validator causing: - # failed validating JWT token sent from peer [...] no jwt validator set - AuthAudience = "netbird"; - }; - TURNConfig = { - Secret._secret = config.age.secrets.coturn-secret.path; - Turns = [ - { - Proto = "udp"; - URI = "turn:${config.services.netbird.server.management.turnDomain}:${builtins.toString config.services.netbird.server.management.turnPort}"; - Username = "netbird"; - Password._secret = config.age.secrets.coturn-password-netbird.path; - } - ]; - }; - DataStoreEncryptionKey._secret = config.age.secrets.netbird-data-store-encryption-key.path; - }; - }; - }; - }; - - globals.services.netbird.domain = netbirdDomain; - globals.monitoring.http.netbird = { - url = "https://${netbirdDomain}/api/users"; - expectedStatus = 401; - expectedBodyRegex = "no valid authentication"; - network = "internet"; - }; - - nodes.sentinel = { - services.nginx = { - upstreams.netbird-mgmt = { - servers."${config.wireguard.proxy-sentinel.ipv4}:${builtins.toString config.services.netbird.server.management.port}" = - { }; - extraConfig = '' - zone netbird 64k; - keepalive 5; - ''; - monitoring = { - enable = true; - path = "/api/users"; - expectedStatus = 401; - expectedBodyRegex = "no valid authentication"; - }; - }; - - upstreams.netbird-signal = { - servers."${config.wireguard.proxy-sentinel.ipv4}:${builtins.toString config.services.netbird.server.signal.port}" = - { }; - extraConfig = '' - zone netbird 64k; - keepalive 5; - ''; - }; - - virtualHosts.${netbirdDomain} = { - forceSSL = true; - useACMEWildcardHost = true; - - locations = { - "/" = { - root = config.services.netbird.server.dashboard.finalDrv; - tryFiles = "$uri $uri.html $uri/ =404"; - X-Frame-Options = "SAMEORIGIN"; - }; - - "/signalexchange.SignalExchange/".extraConfig = '' - grpc_pass grpc://netbird-signal; - grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - grpc_read_timeout 1d; - grpc_send_timeout 1d; - grpc_socket_keepalive on; - ''; - - "/api".proxyPass = "http://netbird-mgmt"; - - "/management.ManagementService/".extraConfig = '' - grpc_pass grpc://netbird-mgmt; - grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - grpc_read_timeout 1d; - grpc_send_timeout 1d; - grpc_socket_keepalive on; - ''; - }; - - # client_body_timeout is necessary so that grpc connections do not get closed early, see https://stackoverflow.com/a/67805465 - extraConfig = '' - client_header_timeout 1d; - client_body_timeout 1d; - client_max_body_size 512M; - ''; - }; - }; - }; - - systemd.services.netbird-signal.serviceConfig.RestartSec = "60"; # Retry every minute - systemd.services.netbird-management.serviceConfig.RestartSec = "60"; # Retry every minute -} diff --git a/hosts/ward/secrets/netbird/host.pub b/hosts/ward/secrets/netbird/host.pub deleted file mode 100644 index 3f2ed92..0000000 --- a/hosts/ward/secrets/netbird/host.pub +++ /dev/null @@ -1 +0,0 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJt2DE0HJjmePYjuZVRcsb0/SfoHSmm06T4ayzIgxUOp diff --git a/modules/default.nix b/modules/default.nix index 260bdb2..fe00f12 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -1,8 +1,4 @@ { - disabledModules = [ - "services/networking/netbird.nix" - ]; - imports = [ ./acme-wildcard.nix ./backups.nix @@ -10,7 +6,6 @@ ./distributed-config.nix ./globals.nix ./meta.nix - ./netbird-client.nix ./nginx-upstream-monitoring.nix ./oauth2-proxy.nix ./promtail.nix diff --git a/modules/netbird-client.nix b/modules/netbird-client.nix deleted file mode 100644 index d3b24d4..0000000 --- a/modules/netbird-client.nix +++ /dev/null @@ -1,546 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: -let - inherit (lib) - attrValues - concatLists - concatStringsSep - escapeShellArgs - filterAttrs - getExe - literalExpression - maintainers - makeBinPath - mapAttrs' - mapAttrsToList - mkDefault - mkIf - mkMerge - mkOption - mkOptionDefault - mkPackageOption - mkRemovedOptionModule - nameValuePair - optional - optionalString - toShellVars - versionAtLeast - versionOlder - ; - - inherit (lib.types) - attrsOf - bool - enum - package - port - str - submodule - ; - - 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; -in -{ - meta.maintainers = with maintainers; [ - misuzu - thubrecht - nazarewk - ]; - - imports = [ - (mkRemovedOptionModule [ - "services" - "netbird" - "tunnels" - ] "The option `services.netbird.tunnels` has been renamed to `services.netbird.clients`") - ]; - - options.services.netbird = { - 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" { }; - - ui.enable = mkOption { - type = bool; - default = config.services.displayManager.sessionPackages != [ ]; - defaultText = literalExpression ''config.services.displayManager.sessionPackages != [ ]''; - 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, - ... - }: - { - options = { - port = mkOption { - type = port; - example = literalExpression "51820"; - description = '' - Port the Netbird client listens on. - ''; - }; - - name = mkOption { - type = str; - default = "netbird-${name}"; - description = '' - Primary name for use 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 = "netbird-${name}"; - description = '' - Name of the network interface managed by this client. - ''; - }; - - environment = mkOption { - type = attrsOf str; - defaultText = literalExpression '' - { - NB_CONFIG = "/var/lib/''${config.name}/config.json"; - NB_DAEMON_ADDR = "unix:///var/run/''${config.name}/sock"; - NB_INTERFACE_NAME = config.interface; - NB_LOG_FILE = mkOptionDefault "console"; - NB_LOG_LEVEL = config.logLevel; - NB_SERVICE = config.name; - NB_WIREGUARD_PORT = toString config.port; - } - ''; - description = '' - Environment for the netbird service, used to pass configuration options. - ''; - }; - - 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 = '' - 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-${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."; - }; - - 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-${name}"; - meta.mainProgram = "netbird-${name}"; - nativeBuildInputs = with pkgs; [ makeWrapper ]; - phases = [ "installPhase" ]; - installPhase = concatStringsSep "\n" [ - '' - mkdir -p "$out/bin" - makeWrapper ${lib.getExe cfg.package} "$out/bin/netbird-${name}" \ - ${escapeShellArgs makeWrapperArgs} - '' - (optionalString cfg.ui.enable '' - # netbird-ui doesn't support envvars - makeWrapper ${lib.getExe cfg.ui.package}-ui "$out/bin/netbird-ui-${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-${name}.desktop" \ - --replace-fail 'Name=Netbird' "Name=Netbird @ ${config.name}" \ - --replace-fail '${lib.getExe cfg.ui.package}-ui' "$out/bin/netbird-ui-${name}" - '') - ]; - }; - }; - - # see https://github.com/netbirdio/netbird/blob/88747e3e0191abc64f1e8c7ecc65e5e50a1527fd/client/internal/config.go#L49-L82 - config = mkOption { - inherit (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-${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/${config.name}/config.json"; - NB_DAEMON_ADDR = "unix:///var/run/${config.name}/sock"; - NB_INTERFACE_NAME = config.interface; - NB_LOG_FILE = mkOptionDefault "console"; - NB_LOG_LEVEL = config.logLevel; - NB_SERVICE = config.name; - NB_WIREGUARD_PORT = toString config.port; - }; - - config.config = { - DisableAutoConnect = !config.autoStart; - WgIface = config.interface; - WgPort = config.port; - }; - } - ) - ); - default = { }; - description = '' - 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 `51830` (`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 ( - 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 "${name}-as-default" { } '' - mkdir -p "$out/bin" - for binary in netbird ${optionalString cfg.ui.enable "netbird-ui"} ; do - ln -s "${client.wrapper}/bin/$binary-${name}" "$out/bin/$binary" - done - '' - )) - ]; - } - )) - { - boot.extraModulePackages = optional ( - cfg.clients != { } && (versionOlder kernel.version "5.6") - ) kernelPackages.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 - ; - - networking.dhcpcd.denyInterfaces = toClientList (client: client.interface); - networking.networkmanager.unmanaged = toClientList (client: "interface-name:${client.interface}"); - - networking.firewall.allowedUDPPorts = concatLists ( - toClientList (client: optional client.openFirewall client.port) - ); - - systemd.network.networks = mkIf config.networking.useNetworkd ( - toClientAttrs ( - client: - nameValuePair "50-netbird-${client.interface}" { - matchConfig = { - Name = client.interface; - }; - linkConfig = { - Unmanaged = true; - ActivationPolicy = "manual"; - }; - } - ) - ); - - environment.etc = toClientAttrs ( - client: - nameValuePair "${client.name}/config.d/50-nixos.json" { - text = builtins.toJSON client.config; - mode = "0444"; - } - ); - - systemd.services = toClientAttrs ( - client: - nameValuePair client.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 = optional (!config.services.resolved.enable) pkgs.openresolv; - - serviceConfig = { - ExecStart = "${getExe client.wrapper} service run"; - Restart = "always"; - - RuntimeDirectory = client.name; - RuntimeDirectoryMode = mkDefault "0755"; - ConfigurationDirectory = client.name; - StateDirectory = client.name; - StateDirectoryMode = "0700"; - - WorkingDirectory = "/var/lib/${client.name}"; - }; - - unitConfig = { - StartLimitInterval = 5; - StartLimitBurst = 10; - }; - - stopIfChanged = false; - } - ); - } - # Hardening section - (mkIf (hardenedClients != { }) { - users.groups = toHardenedClientAttrs (client: nameValuePair client.name { }); - users.users = toHardenedClientAttrs ( - client: - nameValuePair client.name { - isSystemUser = true; - home = "/var/lib/${client.name}"; - group = client.name; - } - ); - - systemd.services = toHardenedClientAttrs ( - client: - nameValuePair client.name ( - mkIf client.hardened { - serviceConfig = { - RuntimeDirectoryMode = "0750"; - - User = client.name; - Group = 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"; - }; - } - ) - ); - - # see https://github.com/systemd/systemd/blob/17f3e91e8107b2b29fe25755651b230bbc81a514/src/resolve/org.freedesktop.resolve1.policy#L43-L43 - security.polkit.extraConfig = mkIf config.services.resolved.enable '' - // systemd-resolved access for Netbird clients - polkit.addRule(function(action, subject) { - var actions = [ - "org.freedesktop.resolve1.set-dns-servers", - "org.freedesktop.resolve1.set-domains", - ]; - var users = ${builtins.toJSON (toHardenedClientList (client: 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 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/${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/${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/secrets/global.nix.age b/secrets/global.nix.age index 1575b280a7efdfd444dc1143ecb176c6d103ef91..83d2b51c43b27b83c6496ad57bf476040c39cc58 100644 GIT binary patch literal 3532 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%0D$SKi0Y@CXvARti z%G?Ao;5F^8I<-Lfr)7aN|7E*x6H(8jgUww3o~r5o&# zTh5+&cn9a9T3&T01#cYAMN)SC>)!OET0TV&&&nxb4xxtBenL zKPT!4(B|5j&TGSIvg+a~u`t5!{7S{3QjkXr?jWh}wlc7*~xf6NLe zh(Fk;-e|Fc@15G_eVUsZaOxE`9A!DT=;V7K=DgAOK!L3iIM1e$qNrIFj1hTxiOq<6 zX3A!P1q+ucG@ODpXeJSTlU%|c)5u8dwMJ%wC!2Z1bKkqd;sA#qRtt;(;iAzMFU)}o z%i%Apq}Ri43SY=ukMY|hmPZB4H|IP?jIh!?U?8yI<~c&V+9t?&u2@Kd?UC89%=Lr@ zZ^Q7Rm?JstjbfdYlabsR-O| zFFAGDNGn4qs=PK)jyz!3&9GD>fj6B-6j2443V*w?LW!FZ_m}fZMt)?+0)c2$PEG7V zJ2mEXS6b4|P#2G~k2X3fJ G12URRc!#P0 literal 3449 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