Files
nixos/modules/vlans.nix
Joakim Repomaa 2a36964fcc refactor vlan and firewall config into modules
fix bug with vlans module

fix vlans
2025-02-08 15:38:50 +02:00

162 lines
3.7 KiB
Nix

{ lib, config, ... }:
let
types = {
portList = lib.types.listOf lib.types.int;
service = lib.types.submodule {
options = {
tcp = lib.mkOption {
type = types.portList;
default = [ ];
};
udp = lib.mkOption {
type = types.portList;
default = [ ];
};
};
};
vlan = lib.types.submodule {
options = {
id = lib.mkOption {
type = lib.types.int;
};
staticLeases = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
};
ipv6 = lib.mkEnableOption "ipv6";
};
};
bridge = lib.types.submodule {
options = {
enable = lib.mkEnableOption "Enable bridge";
pvid = lib.mkOption {
type = lib.types.int;
};
bindNetwork = lib.mkOption {
type = lib.types.str;
};
network = lib.mkOption {
type = lib.types.str;
};
netdev = lib.mkOption {
type = lib.types.str;
};
};
};
};
cfg = config.modules.vlans;
vlans = lib.mapAttrsToList (attrName: { name ? attrName, ... }@vlan: ({ inherit name; } // vlan)) cfg.networks;
vlanAttrs = lib.listToAttrs (lib.map ({ name, ... }@value: { inherit name value; }) vlans);
buildNetdev = name: { id, ... }: {
name = "20-${name}";
value = {
netdevConfig = {
Name = name;
Kind = "vlan";
MACAddress = "00:0d:b9:49:d2:${toString id}";
};
vlanConfig = { Id = id; };
};
};
buildStaticLease = macAddress: address: ''
[DHCPServerStaticLease]
MACAddress=${macAddress}
Address=${address}
'';
buildNetwork = name: { id, ipv6, staticLeases, ... }: {
name = "30-${name}";
value = {
matchConfig = {
Name = name;
};
networkConfig = {
Address = "10.${toString id}.0.1/23";
IPMasquerade = "ipv4";
DHCPServer = true;
IPv6AcceptRA = false;
IPv6SendRA = ipv6;
DHCPPrefixDelegation = ipv6;
};
dhcpServerConfig = {
PoolOffset = 255;
DNS = "10.${toString id}.0.1";
};
extraConfig = lib.concatLines (lib.mapAttrsToList buildStaticLease staticLeases);
};
};
vlanIds = lib.mapAttrsToList (_: { id, ... }: id) vlanAttrs;
vlanRange = {
min = lib.foldr lib.min 999 vlanIds;
max = lib.foldr lib.max 0 vlanIds;
};
bridgeVLANConfig = ''
[BridgeVLAN]
VLAN=${toString vlanRange.min}-${toString vlanRange.max}
EgressUntagged=${toString cfg.bridge.pvid}
PVID=${toString cfg.bridge.pvid}
'';
bridgeNetDev =
if (cfg.bridge.enable) then {
"${cfg.bridge.netdev}".bridgeConfig = {
VLANFiltering = true;
DefaultPVID = cfg.bridge.pvid;
};
} else { };
bridgeBindNetwork =
if (cfg.bridge.enable) then {
${cfg.bridge.bindNetwork}.extraConfig = bridgeVLANConfig;
} else { };
bridgeNetwork =
if (cfg.bridge.enable) then {
"${cfg.bridge.network}" = {
vlan = lib.map ({ name, ... }: name) vlans;
bridgeVLANs = lib.map ({ id, ... }: { VLAN = id; }) vlans;
};
} else { };
netdevs = lib.mergeAttrsList [
(lib.mapAttrs' buildNetdev vlanAttrs)
bridgeNetDev
];
networks = lib.mergeAttrsList [
(lib.mapAttrs' buildNetwork vlanAttrs)
bridgeBindNetwork
bridgeNetwork
];
in
{
options.modules.vlans = {
enable = lib.mkEnableOption "Enable VLANs";
networks = lib.mkOption {
type = lib.types.attrsOf types.vlan;
};
bridge = lib.mkOption {
type = types.bridge;
};
};
config = lib.mkIf cfg.enable {
systemd.network = {
enable = lib.mkDefault true;
inherit netdevs networks;
};
};
}