refactor(access): network interface config

This commit is contained in:
arcnmx 2024-03-23 21:13:01 -07:00
parent ee3834d72a
commit f2fddc1001
42 changed files with 466 additions and 189 deletions

View file

@ -77,6 +77,14 @@ in {
"fe80::/64"
];
};
int = {
v4 = [
"10.9.1.0/24"
];
v6 = [
"fd0c::/64"
];
};
tail = mkIf tailscale.enable {
v4 = [
"100.64.0.0/10"
@ -86,6 +94,24 @@ in {
"fd7a:115c:a1e0:ab12::/64"
];
};
allLan = {
v4 = cfg.cidrForNetwork.loopback.v4
++ cfg.cidrForNetwork.local.v4
++ cfg.cidrForNetwork.int.v4;
v6 = cfg.cidrForNetwork.loopback.v6
++ cfg.cidrForNetwork.local.v6
++ cfg.cidrForNetwork.int.v6;
};
allLocal = {
v4 = mkMerge [
cfg.cidrForNetwork.allLan.v4
(mkIf tailscale.enable cfg.cidrForNetwork.tail.v4)
];
v6 = mkMerge [
cfg.cidrForNetwork.allLan.v6
(mkIf tailscale.enable cfg.cidrForNetwork.tail.v6)
];
};
};
localaddrs = {
nftablesInclude = mkBefore (''

View file

@ -7,7 +7,7 @@
cfg = config.services.home-assistant;
inherit (lib.modules) mkIf mkMerge mkBefore mkDefault mkOptionDefault;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.lists) optional optionals elem unique;
inherit (lib.lists) optional elem unique;
inherit (lib.strings) toLower;
in {
options.services.home-assistant = with lib.types; {
@ -118,9 +118,7 @@ in {
trusted_proxies = let
inherit (config.networking.access) cidrForNetwork;
in
cidrForNetwork.loopback.all
++ cidrForNetwork.local.all
++ optionals config.services.tailscale.enable cidrForNetwork.tail.all
cidrForNetwork.allLocal.all
++ [
"200::/7"
];

View file

@ -9,11 +9,10 @@
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkAfter mkDefault mkOptionDefault;
inherit (lib.attrsets) mapAttrs' mapAttrsToList listToAttrs nameValuePair attrValues;
inherit (lib.lists) singleton optional optionals filter concatMap;
inherit (lib.lists) singleton optional filter concatMap;
inherit (lib.strings) concatStringsSep escapeShellArg;
inherit (utils) escapeSystemdExecArg;
inherit (inputs.self.lib.lib) unmerged;
inherit (config.services) tailscale;
inherit (config) networking;
inherit (networking) access;
enabledNamespaces = filter (ns: ns.enable) (attrValues networking.namespaces);
@ -324,8 +323,8 @@
''
];
extraOutput = let
addrs4 = access.cidrForNetwork.local.v4 ++ optionals tailscale.enable access.cidrForNetwork.tail.v4;
addrs6 = access.cidrForNetwork.local.v6 ++ optionals tailscale.enable access.cidrForNetwork.tail.v6;
addrs4 = access.cidrForNetwork.allLocal.v4;
addrs6 = access.cidrForNetwork.allLocal.v6;
daddr4 = ''{ ${concatStringsSep ", " addrs4} }'';
daddr6 = ''{ ${concatStringsSep ", " addrs6} }'';
in

View file

@ -6,7 +6,6 @@
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkBefore mkOptionDefault;
inherit (lib.strings) concatMapStringsSep optionalString;
inherit (lib.lists) optionals;
inherit (config.services) tailscale;
inherit (config.networking.access) cidrForNetwork localaddrs;
mkAddrVar = remoteAddr: varPrefix: ''
@ -29,6 +28,13 @@
if (${remoteAddr} ~ "^fe80::") {
set ${varPrefix}lan 1;
}
set ${varPrefix}int 0;
if (${remoteAddr} ~ "^10\.9\.1\.[0-9]+") {
set ${varPrefix}lan 1;
}
if (${remoteAddr} ~ "^fd0c::") {
set ${varPrefix}int 1;
}
set ${varPrefix}localhost 0;
if (${remoteAddr} = "::1") {
set ${varPrefix}localhost 1;
@ -43,6 +49,9 @@
if (${varPrefix}lan) {
set ${varPrefix}client 1;
}
if (${varPrefix}int) {
set ${varPrefix}client 1;
}
if (${varPrefix}localhost) {
set ${varPrefix}client 1;
}
@ -79,12 +88,8 @@
config = {
extraConfig = let
mkAllow = cidr: "allow ${cidr};";
allowAddresses =
cidrForNetwork.loopback.all
++ cidrForNetwork.local.all
++ optionals tailscale.enable cidrForNetwork.tail.all;
allows =
concatMapStringsSep "\n" mkAllow allowAddresses
concatMapStringsSep "\n" mkAllow cidrForNetwork.allLocal.all
+ optionalString localaddrs.enable ''
include ${localaddrs.stateDir}/*.nginx.conf;
'';

View file

@ -39,6 +39,9 @@
tailscale = {
allow = mkEnableOption "tailscale TCP connections";
};
int = {
allow = mkEnableOption "internal TCP connections";
};
local = {
allow = mkEnableOption "local TCP connections";
};
@ -55,7 +58,8 @@
in
mkMerge [
(mkIf config.authentication.tailscale.allow cidrForNetwork.tail.all)
(mkIf config.authentication.local.allow (cidrForNetwork.loopback.all ++ cidrForNetwork.local.all))
(mkIf config.authentication.int.allow cidrForNetwork.int.all)
(mkIf config.authentication.local.allow cidrForNetwork.local.all)
];
authentication = mkMerge (map (host: ''
host ${config.authentication.database} ${config.name} ${formatHost host} ${config.authentication.method}

View file

@ -0,0 +1,15 @@
{config, lib, ...}: let
inherit (lib.options) mkOption mkEnableOption;
cfg = config.proxmox.container;
in {
options.proxmox.container = with lib.types; {
enable = mkEnableOption "LXC container";
privileged = mkEnableOption "root";
lxc = {
configJsonFile = mkOption {
type = nullOr path;
default = null;
};
};
};
}

View file

@ -0,0 +1,155 @@
{config, lib, inputs, ...}: let
inherit (inputs.self.lib.lib) unmerged eui64;
inherit (lib.options) mkOption mkEnableOption;
inherit (lib.modules) mkIf mkMerge mkOptionDefault mkOverride;
inherit (lib.attrsets) attrValues;
inherit (lib.lists) elem findSingle;
inherit (lib.strings) hasPrefix removePrefix replaceStrings;
inherit (lib.trivial) toHexString mapNullable;
mkAlmostOptionDefault = mkOverride 1250;
cfg = config.proxmox.network;
internalOffset = 32;
networkInterfaceModule = { config, name, system, ... }: {
options = with lib.types; {
enable = mkEnableOption "network interface" // {
default = true;
};
bridge = mkOption {
type = str;
default = "vmbr0";
};
id = mkOption {
type = str;
default = name;
};
name = mkOption {
type = str;
};
macAddress = mkOption {
type = nullOr str;
default = null;
};
address4 = mkOption {
type = nullOr (either (enum [ "auto" ]) str);
default = null;
};
gateway4 = mkOption {
type = nullOr str;
default = null;
};
address6 = mkOption {
type = nullOr (either (enum [ "auto" "dhcp" ]) str);
default = null;
};
gateway6 = mkOption {
type = nullOr str;
default = null;
};
firewall.enable = mkEnableOption "firewall";
vm.model = mkOption {
type = enum [ "virtio" "e1000" "rtl8139" "vmxnet3" ];
default = "virtio";
};
mdns = {
enable = mkEnableOption "mDNS" // {
default = system.proxmox.node.name == "reisen" && config.id == "net0";
};
};
slaac = {
postfix = mkOption {
type = nullOr str;
};
};
internal = {
enable = mkEnableOption "internal network interface";
};
networkd = {
enable = mkEnableOption "systemd.network" // {
default = true;
};
networkSettings = mkOption {
type = unmerged.types.attrs;
};
};
};
config = let
conf = {
name = mkMerge [
(mkIf (hasPrefix "net" config.id && system.proxmox.container.enable) (mkOptionDefault ("eth" + removePrefix "net" config.id)))
# VMs have names like `ens18` for net0...
];
slaac.postfix = mkOptionDefault (mapNullable eui64 config.macAddress);
gateway4 = mkMerge [
(mkIf (system.proxmox.node.name == "reisen" && config.bridge == "vmbr0" && config.address4 != null && config.address4 != "auto") (mkAlmostOptionDefault "10.1.1.1"))
];
networkd.networkSettings = {
name = mkAlmostOptionDefault config.name;
matchConfig = {
MACAddress = mkIf (config.macAddress != null) (mkOptionDefault config.macAddress);
Type = mkOptionDefault "ether";
};
linkConfig = mkMerge [
(mkIf config.mdns.enable { Multicast = mkOptionDefault true; })
];
networkConfig = mkMerge [
(mkIf (config.address6 == "auto") {
IPv6AcceptRA = true;
})
(mkIf config.mdns.enable {
MulticastDNS = true;
})
];
address = mkMerge [
(mkIf (! elem config.address4 [ null "auto" ]) [ config.address4 ])
(mkIf (! elem config.address6 [ null "auto" "dhcp" ]) [ config.address6 ])
];
gateway = mkMerge [
(mkIf (config.gateway4 != null) [ config.gateway4 ])
(mkIf (config.gateway6 != null) [ config.gateway6 ])
];
DHCP = mkAlmostOptionDefault (
if config.address4 == "auto" && config.address6 == "dhcp" then "yes"
else if config.address6 == "dhcp" then "ipv6"
else if config.address4 == "dhcp" then "ipv4"
else "no"
);
};
};
confInternal = {
name = mkAlmostOptionDefault "eth9";
bridge = mkAlmostOptionDefault "vmbr9";
address4 = mkAlmostOptionDefault "10.9.1.${toString (system.proxmox.vm.id - internalOffset)}/24";
address6 = mkAlmostOptionDefault "fd0c::${toHexString (system.proxmox.vm.id - internalOffset)}/64";
macAddress = mkIf (system.proxmox.network.interfaces.net0.macAddress or null != null && hasPrefix "BC:24:11:" system.proxmox.network.interfaces.net0.macAddress) (mkAlmostOptionDefault (
replaceStrings [ "BC:24:11:" ] [ "BC:24:19:" ] system.proxmox.network.interfaces.net0.macAddress
));
networkd.networkSettings.linkConfig.RequiredForOnline = false;
};
in mkMerge [
conf
(mkIf config.internal.enable confInternal)
];
};
in {
options.proxmox.network = with lib.types; {
interfaces = mkOption {
type = attrsOf (submoduleWith {
modules = [ networkInterfaceModule ];
specialArgs = {
system = config;
};
});
default = { };
};
internal = {
interface = mkOption {
type = nullOr unspecified;
};
};
};
config.proxmox.network = {
internal = {
interface = mkOptionDefault (findSingle (interface: interface.internal.enable) null (throw "expected only one internal network interface") (attrValues cfg.interfaces));
};
};
}

View file

@ -0,0 +1,22 @@
{config, lib, ...}: let
inherit (lib.options) mkOption mkEnableOption;
cfg = config.proxmox;
in {
options.proxmox = with lib.types; {
enabled = mkOption {
type = bool;
default = cfg.vm.enable || cfg.container.enable;
readOnly = true;
};
vm = {
enable = mkEnableOption "QEMU VM";
id = mkOption {
type = int;
};
};
node.name = mkOption {
type = str;
default = "reisen";
};
};
}