From 1d704ccbc8e888bf4e249c6b55ddc8498e8e86d5 Mon Sep 17 00:00:00 2001 From: Asyncnomi Date: Tue, 22 Jul 2025 23:07:45 +0200 Subject: [PATCH] switch to a full networkd setup --- shared/bastion/wireguard.nix | 46 ++++++++++-------- shared/commons/mesh.nix | 90 +++++++++++++++-------------------- shared/commons/networking.nix | 6 --- 3 files changed, 65 insertions(+), 77 deletions(-) diff --git a/shared/bastion/wireguard.nix b/shared/bastion/wireguard.nix index c839fc4..184b2aa 100644 --- a/shared/bastion/wireguard.nix +++ b/shared/bastion/wireguard.nix @@ -12,36 +12,44 @@ let buildSecret = zone: { "wg-private-zone-${toString zone}" = { file = ./../../secrets/bastion + ( "/wg-private-zone-" + toString zone + ".age" ); - owner = "root"; - group = "root"; + owner = "systemd-network"; + group = "systemd-network"; }; }; - peers = map (peerConfig: { - name = "${peerConfig.name}"; - publicKey = peerConfig.publicKey; - allowedIPs = [ + interfacePeers = map (peerConfig: { + PublicKey = peerConfig.publicKey; + AllowedIPs = [ "172.19.${toString (myZone + 127)}.${toString peerConfig.id}/32" "fc00:f::${toString (myZone + 127)}:${toString peerConfig.id}/128" ]; - persistentKeepalive = 25; + PersistentKeepalive = 25; }) users-wg; - interface = { - "mgmt" = { - ips = [ - "172.19.${toString (myZone + 127)}.254/24" - "fc00:f::${toString (myZone + 127)}:254/96" - ]; - privateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}".path; - listenPort = 51920; - peers = peers; - }; + interfaceConfig = { + PrivateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}".path; + ListenPort = 51920; }; in { age.secrets = buildSecret myZone; - # Return all WireGuard interfaces for each node - networking.wireguard.interfaces = interface; + # Build Management interface + systemd.network = { + netdevs."mgmt" = { + netdevConfig = { + Name = "mgmt"; + Kind = "wireguard"; + }; + wireguardConfig = interfaceConfig; + wireguardPeers = interfacePeers; + }; + networks."mgmt" = { + matchConfig.Name = "mgmt"; + address = [ + "172.19.${toString (myZone + 127)}.254/24" + "fc00:f::${toString (myZone + 127)}:254/96" + ]; + }; + }; } \ No newline at end of file diff --git a/shared/commons/mesh.nix b/shared/commons/mesh.nix index ac051a2..85a4405 100644 --- a/shared/commons/mesh.nix +++ b/shared/commons/mesh.nix @@ -13,8 +13,8 @@ let buildSecret = zone: id: { "wg-private-zone-${toString zone}-id-${toString id}" = { file = ./../../secrets/wireguard + ( "/wg-private-zone-" + toString zone + "-id-" + toString id + ".age" ); - owner = "root"; - group = "root"; + owner = "systemd-network"; + group = "systemd-network"; }; }; generatedSecrets = lib.mapAttrsToList (name: node: buildSecret node.zone node.id) nodes; @@ -22,71 +22,57 @@ let # Filter itself out of the peer list peerConfigs = lib.filterAttrs (_peerName: peerConfig: (peerConfig.zone != myZone) || (peerConfig.id != myId)) nodes; - peers = lib.mapAttrsToList (peerName: peerConfig: { - name = "${peerName}"; - publicKey = peerConfig.wg-pub; - allowedIPs = [ + interfacePeers = lib.mapAttrsToList (peerName: peerConfig: { + PublicKey = peerConfig.wg-pub; + AllowedIPs = [ "172.19.${toString peerConfig.zone}.${toString peerConfig.id}/32" "fc00::${toString peerConfig.zone}:${toString peerConfig.id}/128" ] ++ lib.optionals (lib.elem peerName mapping.bastion) [ "172.19.${toString (peerConfig.zone + 127)}.0/24" "fc00:f::${toString (peerConfig.zone + 127)}:0/112" ]; - endpoint = "${builtins.head (builtins.split "/" peerConfig.ip4)}:51820"; - persistentKeepalive = 25; + Endpoint = "${builtins.head (builtins.split "/" peerConfig.ip4)}:51820"; + PersistentKeepalive = 25; }) peerConfigs; - interfaces = { - "mesh" = { - ips = [ - "172.19.${toString myZone}.${toString myId}/17" - "fc00::${toString myZone}:${toString myId}/112" - ]; - privateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}-id-${toString myId}".path; - listenPort = 51820; - peers = peers; - }; + interfaceConfig = { + PrivateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}-id-${toString myId}".path; + ListenPort = 51820; }; - generateRoute = peerName: peerConfig: '' - # Return path for mgmt trafic - ${if lib.elem peerName mapping.bastion then '' - ${pkgs.iproute2}/bin/ip route replace 172.19.${toString (peerConfig.zone + 127)}.0/24 via 172.19.${toString peerConfig.zone}.${toString peerConfig.id} dev mesh - ${pkgs.iproute2}/bin/ip -6 route replace fc00:f::${toString (peerConfig.zone + 127)}:0/112 via fc00::${toString peerConfig.zone}:${toString peerConfig.id} dev mesh - '' else ""} - ''; + # Return route for mgmt traffic + bastionConfigs = lib.filterAttrs (peerName: _peerConfig: lib.elem peerName mapping.bastion) peerConfigs; - generateAfter = peerName: peerConfig: "wireguard-mesh.target"; - - routes = lib.mapAttrsToList (name: peer: generateRoute name peer) peerConfigs; - afters = lib.mapAttrsToList (name: peer: generateAfter name peer) peerConfigs; - - wireguardStaticRoute = pkgs.writeShellScriptBin "wireguardStaticRoute" '' - ${lib.concatStrings routes} - ''; + rtwg4 = map (node: { + Gateway = "172.19.${toString node.zone}.${toString node.id}"; + Destination = "172.19.${toString (node.zone + 127)}.0/24"; + }) (lib.attrValues bastionConfigs); + + rtwg6 = map (node: { + Gateway = "fc00::${toString node.zone}:${toString node.id}"; + Destination = "fc00:f::${toString (node.zone + 127)}:0/112"; + }) (lib.attrValues bastionConfigs); in { age.secrets = lib.lists.foldl' (acc: set: lib.attrsets.recursiveUpdate acc set) {} generatedSecrets; - # Networkd backend introduce in 25.05 - # No independant target are generated - # when using networkd as a backend - # We need them, see below - networking.wireguard.useNetworkd = false; - - # Return all WireGuard interfaces for each node - networking.wireguard.interfaces = interfaces; - - # Execute custom routing for wireguard - systemd.services.wireguardStaticRouting = { - wantedBy = [ "multi-user.target" ]; - # Thus we need specific target to be reached to run it - after = afters; - description = "Add custom ip route for wireguard."; - serviceConfig = { - Type = "oneshot"; - User = "root"; - ExecStart = "${wireguardStaticRoute}/bin/wireguardStaticRoute"; + # Build Mesh interface + systemd.network = { + netdevs."mesh" = { + netdevConfig = { + Name = "mesh"; + Kind = "wireguard"; + }; + wireguardConfig = interfaceConfig; + wireguardPeers = interfacePeers; + }; + networks."mesh" = { + matchConfig.Name = "mesh"; + address = [ + "172.19.${toString myZone}.${toString myId}/17" + "fc00::${toString myZone}:${toString myId}/112" + ]; + routes = rtwg4 ++ rtwg6; }; }; } \ No newline at end of file diff --git a/shared/commons/networking.nix b/shared/commons/networking.nix index 1f3101e..a604e50 100644 --- a/shared/commons/networking.nix +++ b/shared/commons/networking.nix @@ -35,11 +35,5 @@ in linkConfig.RequiredForOnline = "routable"; }; }; - - config.addRouteTablesToIPRoute2 = true; - config.routeTables = { - # Act as a route bin - off = 999; - }; }; } \ No newline at end of file