{ config, lib, ... }: let # Import nodes nodes = import ./../../nodes.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; generateWireGuardInterfaces = nodesConfig: let myPeer = nodesConfig."${config.hostName}"; myZone = myPeer.zone; myId = myPeer.id; # Filter itself out of the peer list peerConfigs = lib.filterAttrs (_peerName: peerConfig: peerConfig.id != myId) nodesConfig; # We'll make one if per peer, this is more flexible interfacePeers = lib.flatten (lib.mapAttrsToList (peerName: peerConfig: let remoteId = peerConfig.id; # The mesh is for now only IPv4 based if4 = { "mesh-${peerName}" = { ips = [ "172.19.${toString remoteId}.${toString myId}/32" "fc00::${toString remoteId}:${toString myId}/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 = [ "172.19.${toString myId}.${toString remoteId}/32" "fc00::${toString myId}:${toString remoteId}/128" # Allow mgmt transport "172.19.128.0/17" "fc00:f::/96" ]; persistentKeepalive = 25; }]; }; }; in if4) peerConfigs); interfaces = builtins.foldl' (acc: set: acc // set) {} interfacePeers; in interfaces; wireguardInterfaces = generateWireGuardInterfaces nodes; 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 # If custom systemd ordering is needed # between wg interface and the rest of # networking: switch to false here # Note: if you turn it off it will break # the custom routing for mgmt rt path # trafic handle by networkd, see networking.nix networking.wireguard.useNetworkd = true; # Return all WireGuard interfaces for each node networking.wireguard.interfaces = wireguardInterfaces; # Open UDP port for wireguard traffic networking.firewall.allowedUDPPorts = lib.range 51000 52000; }