{ config, lib, ... }: let inherit (lib) mkOption types; cfg = config.infra-net; leafSubmodule = lib.types.submodule { options = { mac = mkOption { type = types.str; description = '' Adresse MAC de l'interface préexistante sur le réseau INFRA. ''; example = "AA:BB:CC:DD:EE:FF"; }; id = mkOption { type = types.ints.between 1 65535; description = '' Identifiant de la machine dans le réseau INFRA. ''; example = 194; }; }; }; hubDefSubmodule = lib.type.submodule { options = { hid = mkOption { type = types.ints.between 1 255; description = '' Identifiant du concentrateur sur la maille WireGuard. ''; example = 12; }; public-key = mkOption { type = types.str; description = '' Clé publique WireGuard du concentrateur. ''; example = "LwhiJgtHtYQT4Ug6tgD0RDlUhhNga5tIyiWN2A6dCnk="; }; address = mkOption { type = types.str; description = '' Adresse IP publique du concentrateur. ''; example = "1.2.3.4"; }; port = mkOption { type = types.port; description = '' Port WireGuard public du concentrateur. ''; default = 51039; example = 51039; }; }; }; hubSubmodule = lib.types.submodule { options = { name = mkOption { type = types.str; description = '' Nom d'hôte du concentrateur. ''; default = config.networking.hostName; }; all-hubs = mkOption { type = types.attrsOf hubDefSubmodule; description = '' Définitions de l'ensemble des concentrateurs. ''; }; private-key-path = mkOption { type = types.path; description = '' Chemin vers la clé privée WireGuard du concentrateur. ''; }; wg-port = mkOption { type = types.port; description = '' Port d'écoute WireGuard du concentrateur. ''; default = 51039; example = 51039; }; id = mkOption { type = types.ints.between 1 65535; description = '' Identifiant de la machine dans le réseau INFRA. ''; example = 194; }; mac = mkOption { type = types.str; description = '' Adresse MAC de l'interface virtuelle à du concentrateur sur le réseau INFRA. ''; example = "AA:BB:CC:DD:EE:FF"; }; }; }; mkAddresses = id: let a = id / 256; b = id - 256 * a; in [ "fd0a:66d3:1c19:42::${toString a}:${toString b}/64" "10.42.${toString a}.${toString b}/16" ]; mkHubAddress = hub: "fd0a:66d3:1c19:1000::${toString hub.hid}"; mkPeer = hub: { PublicKey = hub.public-key; Endpoint = "${hub.address}:${hub.port}"; AllowedIPs = mkHubAddress hub; }; vxlanPort = 4789; vni = 42; selfHub = cfg.hub.all-hubs."${cfg.hub.name}"; otherHubs = lib.filterAttrs (n: _: n != cfg.hub.name) cfg.hub.all-hubs; mkBridgeFDB = hub: { MACAddress = "00:00:00:00:00:00"; Destination = "${mkHubAddress hub}"; VNI = vni; }; in { options.infra-net = { leaf = mkOption { type = types.nullOr leafSubmodule; default = null; description = '' Configuration de l'interface d'une feuille du réseau INFRA. ''; }; hub = lib.mkOption { type = lib.types.nullOr hubSubmodule; default = null; description = '' Configuration des interfaces d'un concentrateur du réseau INFRA. ''; }; }; config = let hubNetwork = { links = { "10-wg-infra" = { netdevConfig = { Name = "wg-infra"; Kind = "wireguard"; }; wireguardConfig = { ListenPort = cfg.hub.wg-port; PrivateKey = "@wg-infra-key"; }; wireguardPeers = map mkPeer otherHubs; }; "10-vxl-infra" = { netdevConfig = { Name = "vxl-infra"; Kind = "vxlan"; }; vxlanConfig = { Local = mkHubAddress selfHub; VNI = vni; MacLearning = true; DestinationPort = vxlanPort; }; }; "10-br-infra".netdevConfig = { Name = "br-infra"; Kind = "bridge"; MACAddress = cfg.hub.mac; }; }; networks = { "10-wg-infra" = { matchConfig.Name = "wg-infra"; networkConfig = { Address = "${mkHubAddress selfHub}/64"; 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"; address = mkAddresses cfg.hub.id; }; }; }; leafNetwork = { links."10-infra" = { matchConfig.MACAddress = cfg.leaf.mac; linkConfig.Name = "infra"; }; networks."10-infra" = { matchConfig.Name = "infra"; address = mkAddresses cfg.leaf.id; }; }; in { systemd.network = lib.mkMerge [ (lib.mkIf (cfg.hub != null) hubNetwork) (lib.mkIf (cfg.leaf != null) leafNetwork) ]; systemd.services.systemd-networkd.serviceConfig.LoadCredential = lib.mkIf (cfg.hub != null) [ "wg-infra-key:${cfg.hub.private-key-path}" ]; }; }