nix/shared/commons/mesh.nix

92 lines
No EOL
3.5 KiB
Nix

{ 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;
# 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 = [
"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;
}) 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;
};
};
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 ""}
'';
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}
'';
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";
};
};
}