179 lines
5.1 KiB
Nix
179 lines
5.1 KiB
Nix
# ISC DHCP/IPv4 server configuration
|
|
{ hostName, config, lib, ... }:
|
|
|
|
let
|
|
dhcpNets =
|
|
lib.filterAttrs (_: { dhcp, ... }:
|
|
dhcp != null &&
|
|
dhcp.server == hostName
|
|
) config.site.net;
|
|
|
|
concatMapDhcpNets = f:
|
|
lib.pipe dhcpNets [
|
|
(builtins.mapAttrs f)
|
|
builtins.attrValues
|
|
(map (r: if builtins.isList r then r else [ r ]))
|
|
builtins.concatLists
|
|
];
|
|
|
|
enabled = builtins.length (builtins.attrNames dhcpNets) > 0;
|
|
in
|
|
{
|
|
services.kea.dhcp4 = lib.optionalAttrs enabled {
|
|
enable = true;
|
|
|
|
settings = {
|
|
interfaces-config.interfaces = builtins.attrNames dhcpNets;
|
|
dhcp-ddns.enable-updates = true;
|
|
|
|
subnet4 = concatMapDhcpNets (net: { vlan, subnet4, dhcp, domainName, ... }: {
|
|
id = vlan;
|
|
subnet = subnet4;
|
|
pools = [ {
|
|
pool = "${dhcp.start} - ${dhcp.end}";
|
|
} ];
|
|
rebind-timer = dhcp.time;
|
|
valid-lifetime = dhcp.max-time;
|
|
option-data = [ {
|
|
space = "dhcp4";
|
|
name = "routers";
|
|
code = 3;
|
|
data = config.site.net.${net}.hosts4.${dhcp.router};
|
|
} {
|
|
space = "dhcp4";
|
|
name = "domain-name";
|
|
code = 15;
|
|
data = domainName;
|
|
} {
|
|
space = "dhcp4";
|
|
name = "domain-name-servers";
|
|
code = 6;
|
|
data = "172.20.73.8, 9.9.9.9";
|
|
} ];
|
|
});
|
|
|
|
match-client-id = false;
|
|
host-reservation-identifiers = [ "hw-address" ];
|
|
reservations = concatMapDhcpNets (net: { hosts4, dhcp, ... }:
|
|
builtins.attrValues (
|
|
builtins.mapAttrs (name: hwaddr: {
|
|
hostname = "${name}.${net}.zentralwerk.org";
|
|
hw-address = hwaddr;
|
|
ip-address = hosts4.${name};
|
|
}) dhcp.fixed-hosts
|
|
));
|
|
|
|
# Netbooting
|
|
option-def = [ {
|
|
name = "PXEDiscoveryControl";
|
|
code = 6;
|
|
space = "vendor-encapsulated-options-space";
|
|
type = "uint8";
|
|
array = false;
|
|
} {
|
|
name = "PXEMenuPrompt";
|
|
code = 10;
|
|
space = "vendor-encapsulated-options-space";
|
|
type = "record";
|
|
array = false;
|
|
record-types = "uint8,string";
|
|
} {
|
|
name = "PXEBootMenu";
|
|
code = 9;
|
|
space = "vendor-encapsulated-options-space";
|
|
type = "record";
|
|
array = false;
|
|
record-types = "uint16,uint8,string";
|
|
} ];
|
|
client-classes =
|
|
let
|
|
rpi4Class = {
|
|
name = "rpi4-pxe";
|
|
test = "option[vendor-class-identifier].text == 'PXEClient:Arch:00000:UNDI:002001'";
|
|
option-data = [ {
|
|
name = "boot-file-name";
|
|
data = "bootcode.bin";
|
|
} {
|
|
name = "vendor-class-identifier";
|
|
data = "PXEClient";
|
|
} {
|
|
name = "vendor-encapsulated-options";
|
|
} {
|
|
name = "PXEBootMenu";
|
|
csv-format = true;
|
|
data = "0,17,Raspberry Pi Boot";
|
|
space = "vendor-encapsulated-options-space";
|
|
} {
|
|
name = "PXEDiscoveryControl";
|
|
data = "3";
|
|
space = "vendor-encapsulated-options-space";
|
|
} {
|
|
name = "PXEMenuPrompt";
|
|
csv-format = true;
|
|
data = "0,PXE";
|
|
space = "vendor-encapsulated-options-space";
|
|
} ];
|
|
};
|
|
|
|
pxeClassData = {
|
|
PXE-Legacy = {
|
|
arch = "00000";
|
|
boot-file-name = "netboot.xyz.kpxe";
|
|
};
|
|
PXE-UEFI-32-1.arch = "00002";
|
|
PXE-UEFI-32-2.arch = "00006";
|
|
PXE-UEFI-64-1.arch = "00007";
|
|
PXE-UEFI-64-2.arch = "00008";
|
|
PXE-UEFI-64-3.arch = "00009";
|
|
};
|
|
|
|
makePxe = name: { boot-file-name ? "netboot.xyz.efi", arch }: {
|
|
inherit name boot-file-name;
|
|
test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:${arch}'";
|
|
next-server = config.site.net.serv.hosts4.nfsroot;
|
|
};
|
|
in
|
|
[ rpi4Class ]
|
|
++
|
|
builtins.attrValues (
|
|
builtins.mapAttrs makePxe pxeClassData
|
|
);
|
|
};
|
|
};
|
|
services.kea.dhcp-ddns = lib.optionalAttrs enabled {
|
|
enable = true;
|
|
|
|
settings = {
|
|
tsig-keys = [ {
|
|
name = "dyndns";
|
|
algorithm = "hmac-sha256";
|
|
secret = config.site.dyndnsKey;
|
|
} ];
|
|
|
|
forward-ddns.ddns-domains = concatMapDhcpNets (net: { domainName, ... }: {
|
|
name = "${domainName}.";
|
|
key-name = "dyndns";
|
|
dns-servers = [ {
|
|
ip-address = config.site.net.serv.hosts4.dns;
|
|
} {
|
|
ip-address = config.site.net.serv.hosts6.dn42.dns;
|
|
} ];
|
|
});
|
|
reverse-ddns.ddns-domains = map ({ name, ...}: {
|
|
name = "${name}.";
|
|
key-name = "dyndns";
|
|
dns-servers = [ {
|
|
ip-address = config.site.net.serv.hosts4.dns;
|
|
} {
|
|
ip-address = config.site.net.serv.hosts6.dn42.dns;
|
|
} ];
|
|
}) (
|
|
builtins.filter ({ name, dynamic, ... }:
|
|
dynamic &&
|
|
lib.hasSuffix ".in-addr.arpa" name
|
|
) config.site.dns.localZones
|
|
);
|
|
};
|
|
};
|
|
}
|