{ config, lib, pkgs, network, name, ... }: let cfg = config.infra; node = network.infra.nodes.${name}; hub = network.infra.hubs.${name}; isHub = cfg.hub != null; address = [ "${node.ipv4}/${toString network.infra.cidr.nodes.ipv4}" "${node.ipv6}/${toString network.infra.cidr.nodes.ipv6}" ]; otherHubs = let filtered = lib.filterAttrs (n: _: n != name) network.infra.hubs; in lib.attrValues filtered; mkBridgeFDB = hub: { MACAddress = "00:00:00:00:00:00"; Destination = "${hub.ipv6}"; VNI = network.infra.vxlan.vni; }; mkPeer = hub: { PublicKey = hub.publicKey; Endpoint = hub.endpoint; PersistentKeepalive = 25; AllowedIPs = [ "${hub.ipv6}" ]; }; iface = if isHub then "br-infra" else "infra"; hubNetwork = { netdevs = { "10-wg-infra" = { netdevConfig = { Name = "wg-infra"; Kind = "wireguard"; }; wireguardConfig = { ListenPort = cfg.hub.wireguardPort; PrivateKey = "@wg-infra-key"; }; wireguardPeers = map mkPeer otherHubs; }; "10-vxl-infra" = { netdevConfig = { Name = "vxl-infra"; Kind = "vxlan"; }; vxlanConfig = { Local = hub.ipv6; VNI = network.infra.vxlan.vni; MacLearning = true; DestinationPort = network.infra.vxlan.port; }; }; "10-br-infra".netdevConfig = { Name = "br-infra"; Kind = "bridge"; }; }; networks = { "10-wg-infra" = { matchConfig.Name = "wg-infra"; networkConfig = { Address = "${hub.ipv6}/${toString network.infra.cidr.hubs.ipv6}"; VXLAN = "vxl-infra"; }; }; "10-vxl-infra" = { matchConfig.Name = "vxl-infra"; networkConfig = { LinkLocalAddressing = false; Bridge = "br-infra"; }; bridgeFDBs = map mkBridgeFDB otherHubs; }; "10-br-infra" = { matchConfig.Name = "br-infra"; linkConfig.MACAddress = node.mac; address = address; }; }; }; leafNetwork = { links."10-infra" = { matchConfig.MACAddress = node.mac; linkConfig.Name = "infra"; }; networks."10-infra" = { matchConfig.Name = "infra"; address = address; }; }; hubFirewall = { wg-infra.allowedUDPPorts = [ network.infra.vxlan.port ]; br-infra = { allowedTCPPorts = cfg.firewall.allowedTCPPorts; allowedUDPPorts = cfg.firewall.allowedUDPPorts; }; }; leafFirewall.infra = { allowedTCPPorts = cfg.firewall.allowedTCPPorts; allowedUDPPorts = cfg.firewall.allowedUDPPorts; }; in { options.infra = { enable = lib.mkEnableOption "Réseau INFRA"; hub = lib.mkOption { type = lib.types.nullOr (lib.types.submodule { options = { privateKeyPath = lib.mkOption { type = lib.types.path; description = '' Chemin vers la clé privée WireGuard du concentrateur. ''; }; wireguardPort = lib.mkOption { type = lib.types.port; description = '' Port d'écoute WireGuard du concentrateur. ''; default = 51039; example = 51039; }; }; }); default = null; description = '' Configuration d'un concentrateur du réseau INFRA. ''; }; firewall = { allowedTCPPorts = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ]; example = [ 443 9100 ]; description = '' Ports TCP autorisés sur le réseau INFRA. ''; }; allowedUDPPorts = lib.mkOption { type = lib.types.listOf lib.types.port; default = [ ]; example = [ 53 ]; description = '' Ports UDP autorisés sur le réseau INFRA. ''; }; }; }; config = lib.mkIf cfg.enable { systemd.network = lib.mkMerge [ (lib.mkIf isHub hubNetwork) (lib.mkIf (!isHub) leafNetwork) ]; environment.systemPackages = lib.mkIf isHub [ pkgs.wireguard-tools ]; networking.firewall.interfaces = lib.mkMerge [ (lib.mkIf isHub hubFirewall) (lib.mkIf (!isHub) leafFirewall) ]; systemd.services.systemd-networkd = { serviceConfig.LoadCredential = lib.mkIf isHub [ "wg-infra-key:${cfg.hub.privateKeyPath}" ]; }; }; }