{ config, lib, pkgs, ... }: let # Import nodes nodes = import ./../../nodes.nix; myPeer = nodes."${config.hostName}"; myId = myPeer.id; myZone = myPeer.zone; # And mappings mapping = import ./../../mapping.nix; 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"; }; }; generatedSecrets = lib.mapAttrsToList (name: node: buildSecret node.zone node.id) nodes; shorten = peerName: let parts = lib.splitString "-" peerName; shortened = lib.concatStrings (map (part: lib.substring 0 1 part) parts); in shortened; # Filter itself out of the peer list peerConfigs = lib.filterAttrs (_peerName: peerConfig: peerConfig.id != myId) nodes; # We'll make one if per peer, this is more flexible interfacePeers = lib.flatten (lib.mapAttrsToList (peerName: peerConfig: let remoteId = peerConfig.id; remoteZone = peerConfig.zone; # The mesh is for now only IPv4 based if4 = { "mesh-${shorten peerName}-${toString remoteZone}-${toString remoteId}" = { ips = [ "172.19.${toString myId}.${toString myId}/32" "172.19.${toString myId}.${toString remoteId}/32" "fc00::${toString myId}:${toString myId}/128" "fc00::${toString myId}:${toString remoteId}/128" ]; privateKeyFile = config.age.secrets."wg-private-zone-${toString myZone}-id-${toString myId}".path; listenPort = 51000 + remoteId; peers = [{ name = "${peerName}-ip4"; publicKey = peerConfig.wg-pub; allowedIPs = [ # Allow mesh trafic "172.19.${toString peerConfig.id}.0/24" "fc00::${toString peerConfig.id}:0/96" # Allow mgmt transport "172.19.128.0/17" "fc00:f::/96" ]; endpoint = "${builtins.head (builtins.split "/" peerConfig.ip4)}:${toString (51000 + myId)}"; persistentKeepalive = 25; }]; # Throw away route created by wireguard table = "off"; }; }; in if4) peerConfigs); wireguardInterfaces = builtins.foldl' (acc: set: acc // set) {} interfacePeers; generateRoute = peerName: peerConfig: '' # Static route to declare static wireguard peer inner tunnel ip (that has been thrown away to the "off" table) ${pkgs.iproute2}/bin/ip route replace 172.19.${toString peerConfig.id}.0/24 dev mesh-${shorten peerName}-${toString peerConfig.zone}-${toString peerConfig.id} scope link ${pkgs.iproute2}/bin/ip -6 route replace fc00::${toString peerConfig.id}:0/112 dev mesh-${shorten peerName}-${toString peerConfig.zone}-${toString peerConfig.id} scope link # 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.id}.${toString myId} dev mesh-${shorten peerName}-${toString peerConfig.zone}-${toString peerConfig.id} ${pkgs.iproute2}/bin/ip -6 route replace fc00:f::${toString (peerConfig.zone + 127)}:0/112 via fc00::${toString peerConfig.id}:${toString myId} dev mesh-${shorten peerName}-${toString peerConfig.zone}-${toString peerConfig.id} '' else ""} ''; generateAfter = peerName: peerConfig: "wireguard-mesh-${shorten peerName}-${toString peerConfig.zone}-${toString peerConfig.id}.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} ''; 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 = wireguardInterfaces; # 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"; }; }; }