{ flake, config, pkgs, lib, ... }: with lib; { config = { services.kea = { dhcp4 = { enable = true; settings = { valid-lifetime = 4000; rebind-timer = 2000; renew-timer = 1000; interfaces-config = { interfaces = [ "lan" "mgmt" ]; }; lease-database = { name = "/var/lib/kea/dhcp4.leases"; persist = true; type = "memfile"; }; client-classes = [ { name = "eostre-ipxe"; test = "hexstring(pkt4.mac, ':') == '00:d8:61:79:c5:40' and option[77].hex == 'iPXE'"; next-server = "10.141.0.1"; boot-file-name = "http://nfsroot.vidhar.yggdrasil/eostre/netboot.ipxe"; only-if-required = true; } { name = "ipxe"; test = "option[77].hex == 'iPXE'"; next-server = "10.141.0.1"; boot-file-name = "http://nfsroot.vidhar.yggdrasil/installer-x86_64-linux/netboot.ipxe"; only-if-required = true; } { name = "uefi-64"; test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00007' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00008' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00009'"; only-if-required = true; option-data = [ { name = "tftp-server-name"; data = "10.141.0.1"; } ]; boot-file-name = "ipxe.efi"; } { name = "uefi-32"; test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00002' or substring(option[60].hex,0,20) == 'PXEClient:Arch:00006'"; only-if-required = true; option-data = [ { name = "tftp-server-name"; data = "10.141.0.1"; } ]; boot-file-name = "i386-ipxe.efi"; } { name = "legacy"; test = "substring(option[60].hex,0,20) == 'PXEClient:Arch:00000'"; only-if-required = true; option-data = [ { name = "tftp-server-name"; data = "10.141.0.1"; } ]; boot-file-name = "undionly.kpxe"; } ]; dhcp-ddns.enable-updates = true; ddns-send-updates = false; ddns-override-client-update = true; ddns-override-no-update = true; ddns-replace-client-name = "when-not-present"; ddns-generated-prefix = "noname"; ddns-update-on-renew = true; subnet4 = [ { subnet = "10.141.0.0/24"; option-data = [ { name = "domain-name-servers"; data = "10.141.0.1"; } { name = "broadcast-address"; data = "10.141.0.255"; } { name = "routers"; data = "10.141.0.1"; } { name = "domain-name"; data = "yggdrasil"; } { name = "domain-search"; data = "lan.yggdrasil, yggdrasil"; } ]; ddns-send-updates = true; ddns-qualifying-suffix = "lan.yggdrasil"; pools = [ { pool = "10.141.0.128 - 10.141.0.254"; } ]; require-client-classes = map (cc: cc.name) config.services.kea.dhcp4.settings.client-classes; reservations = [ { hostname = "sif"; hw-address = "3c:e1:a1:52:24:35"; } { hostname = "sif"; hw-address = "ee:32:68:76:83:ac"; } { hostname = "sif"; hw-address = "48:2a:e3:64:62:97"; } { hostname = "eos"; hw-address = "00:d8:61:79:c5:40"; } { hostname = "geri"; hw-address = "0e:e6:43:5e:37:7b"; } ]; } { subnet = "10.141.1.0/24"; option-data = [ { name = "domain-name-servers"; data = "10.141.1.1"; } { name = "broadcast-address"; data = "10.141.1.255"; } { name = "ntp-servers"; data = "10.141.1.1"; } { name = "domain-name"; data = "yggdrasil"; } { name = "domain-search"; data = "mgmt.yggdrasil, yggdrasil"; } ]; ddns-send-updates = true; ddns-qualifying-suffix = "mgmt.yggdrasil"; pools = [ { pool = "10.141.1.128 - 10.141.1.254"; } ]; reservations = [ { hostname = "switch01"; hw-address = "60:a4:b7:53:94:b5"; ip-address = "10.141.1.2"; } { hostname = "ap01"; hw-address = "74:ac:b9:29:ad:9a"; ip-address = "10.141.1.4"; } ]; } { subnet = "10.141.2.0/24"; option-data = [ { name = "domain-name-servers"; data = "10.141.2.1"; } { name = "broadcast-address"; data = "10.141.2.255"; } { name = "routers"; data = "10.141.2.1"; } ]; ddns-send-updates = false; pools = [ { pool = "10.141.2.128 - 10.141.2.254"; } ]; reservations = []; } ]; }; }; # dhcp6 = { # enable = true; # settings = { # interfaces-config = { # interfaces = [ "lan" ]; # }; # lease-database = { # name = "/var/lib/kea/dhcp6.leases"; # persist = true; # type = "memfile"; # }; # }; # }; dhcp-ddns = { enable = true; settings = { forward-ddns = { ddns-domains = [ { name = "yggdrasil."; dns-servers = [ { ip-address = "127.0.0.1"; port = 5353; key-name = "local_key"; } ]; } ]; }; reverse-ddns = { ddns-domains = [ { name = "141.10.in-addr.arpa."; dns-servers = [ { ip-address = "127.0.0.1"; port = 5353; key-name = "local_key"; } ]; } ]; }; }; }; }; systemd.services.kea-dhcp-ddns-server = { preStart = let configLines = [ "" ] ++ mapAttrsToList (k: v: "\"${k}\": ${builtins.toJSON v}" ) config.services.kea.dhcp-ddns.settings; config-template = pkgs.writeText "dhcp-ddns.conf" '' {"DhcpDdns": { ${concatStringsSep ",\n " configLines} }} ''; in '' ${pkgs.envsubst}/bin/envsubst -i "${config-template}" -o "''${RUNTIME_DIRECTORY}/dhcp-ddns.conf" ''; serviceConfig = { ExecStart = mkForce '' ${pkgs.kea}/bin/kea-dhcp-ddns -c "''${RUNTIME_DIRECTORY}/dhcp-ddns.conf" ${escapeShellArgs config.services.kea.dhcp-ddns.extraArgs} ''; LoadCredential = [ "knot-tsig.json.frag:${config.sops.secrets."kea-knot-tsig.json.frag".path}" ]; }; }; sops.secrets."kea-knot-tsig.json.frag" = { format = "binary"; sopsFile = ./knot-tsig.json.frag; }; services.nginx.virtualHosts."nfsroot.vidhar.yggdrasil" = { addSSL = false; forceSSL = false; locations."/" = { extraConfig = '' autoindex on; ''; root = pkgs.symlinkJoin { name = "nfsroot.vidhar.yggdrasil"; paths = (map (system: let installerBuild = (flake.nixosConfigurations.${"installer-${system}-nfsroot"}.extendModules { modules = [ ({ ... }: { config.nfsroot.storeDevice = "10.141.0.1:nix-store"; config.nfsroot.registrationUrl = "http://nfsroot.vidhar.yggdrasil/installer-${system}/registration"; }) ]; }).config.system.build; in builtins.toPath (pkgs.runCommandLocal "install-${system}" {} '' mkdir -p $out/installer-${system} install -m 0444 -t $out/installer-${system} \ ${installerBuild.initialRamdisk}/initrd \ ${installerBuild.kernel}/bzImage \ ${installerBuild.netbootIpxeScript}/netboot.ipxe \ ${pkgs.closureInfo { rootPaths = installerBuild.storeContents; }}/registration '') ) ["x86_64-linux"] ) ++ [ (let eostreBuild = (flake.nixosConfigurations.eostre.extendModules { modules = [ ({ ... }: { config.nfsroot.storeDevice = "10.141.0.1:nix-store"; config.nfsroot.registrationUrl = "http://nfsroot.vidhar.yggdrasil/eostre/registration"; }) ]; }).config.system.build; in builtins.toPath (pkgs.runCommandLocal "eostre" {} '' mkdir -p $out/eostre install -m 0444 -t $out/eostre \ ${eostreBuild.initialRamdisk}/initrd \ ${eostreBuild.kernel}/bzImage \ ${eostreBuild.netbootIpxeScript}/netboot.ipxe \ ${pkgs.closureInfo { rootPaths = eostreBuild.storeContents; }}/registration '')) ]; }; }; }; systemd.services."pxe-atftpd" = { description = "TFTP Server for PXE Booting"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig.ExecStart = let ipxe = pkgs.ipxe.override { additionalTargets = { "bin-i386-efi/ipxe.efi" = "i386-ipxe.efi"; }; additionalOptions = [ "NSLOOKUP_CMD" ]; }; tftpRoot = pkgs.runCommandLocal "netboot" {} '' mkdir -p $out install -m 0444 -t $out \ ${ipxe}/ipxe.efi ${ipxe}/i386-ipxe.efi ${ipxe}/undionly.kpxe ''; in "${pkgs.atftp}/sbin/atftpd --daemon --no-fork --bind-address=10.141.0.1 ${tftpRoot}"; }; }; }