{ config, flakes, lib, pkgs, ... }: with lib; let cfg = config.local.web.sites.pxe; pxeEnabled = machine: machine.config.local.boot.pxe.enable; machines = listToAttrs (map (name: { inherit name; value = flakes.self.nixosConfigurations.${name}; }) cfg.machines); stage2For = name: machine: # https://purpleidea.com/blog/2025/01/23/working-around-an-ipxe-issue/ # "The answer: # They told me that one of their engineers had struggled with the same issue for a while. The solution: # Add the imgfree iPXE command before you boot! # I wish the docs would hint that this is often required, but now I know, and now you know too! # You can see that line here." pkgs.writeText "stage2-${name}.ipxe" '' #!ipxe echo stage2: booting ${name}... imgfree kernel kernel init=${machine.config.system.build.toplevel}/init ${concatStringsSep " " machine.config.boot.kernelParams} || goto fail initrd initrd || goto fail boot || :fail echo stage2: failed, rebooting in 5 seconds... sleep 5 reboot --warm ''; machineLocations = name: machine: let mac = machine.config.local.boot.pxe.mac; build = machine.config.system.build; in { "= /${mac}/initrd".alias = "${build.initialRamdisk}/initrd"; "= /${mac}/kernel".alias = "${build.kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target}"; "= /${mac}/stage2.ipxe".alias = "${stage2For name machine}"; }; in { options.local.web.sites.pxe = { enable = mkEnableOption "PXE netboot image server"; linkLocal6 = mkOption { type = types.str; }; network = mkOption { type = types.str; }; machines = mkOption { type = types.listOf types.str; default = []; }; }; config = mkIf cfg.enable { assertions = mapAttrsToList (name: machine: { message = "PXE boot is not enabled in config '${name}'"; assertion = pxeEnabled machine; }) machines; local.web.enable = mkDefault true; networking = { firewall.extraCommands = '' ip6tables -t filter -A local-input -p udp -i ${cfg.network} --dport 1792 -d ${cfg.linkLocal6} -j ACCEPT ''; }; services = { nginx = { virtualHosts = { "[${cfg.linkLocal6}]" = { listenAddresses = ["[${cfg.linkLocal6}]"]; addSSL = false; forceSSL = false; locations = mergeAttrsList (mapAttrsToList machineLocations (filterAttrs (_: pxeEnabled) machines)); }; }; }; }; systemd = { network = { networks.${cfg.network}.addresses = [ { Address = "${cfg.linkLocal6}/128"; AddPrefixRoute = "no"; PreferredLifetime = "0"; } ]; }; services = { pxe-store-upload = { path = [config.nix.package pkgs.sshfs pkgs.squashfsTools]; script = let host = lib.throw "TODO: pxe host"; machine = machines.${host}; in '' set -e pxe_ip='${machine.config.local.boot.pxe.linkLocal6}' pxe_host='${host}' pxe_system='${machine.config.system.build.toplevel}' mountpoint="./pxe-initrd.$pxe_host" store_img="$mountpoint/nix-store.squashfs" mkdir -p "$mountpoint" export PATH="/run/wrappers/bin:$PATH" sshfs \ "root@[$pxe_ip%${cfg.network}]:/nix/.ro-store-img/" \ "$mountpoint" \ -o idmap=user nix-store --query --requisites "$pxe_system" | \ xargs -I{} mksquashfs {} - \ -stream -comp zstd -one-file-system -no-xattrs \ >"$store_img.tmp" mksquashfs -fix "$store_img.tmp" sync "$store_img.tmp" mv -- "$store_img.tmp" "$store_img" fusermount3 -u "$mountpoint" ''; serviceConfig = { #AmbientCapabilities = ["CAP_SYS_ADMIN"]; #CapabilityBoundingSet = ["CAP_SYS_ADMIN"]; #BindPaths = ["/dev/fuse"]; #BindReadOnlyPaths = ["/nix/store"]; #DeviceAllow = ["/dev/fuse rwm"]; #DevicePolicy = "closed"; #MountAPIVFS = true; ProtectSystem = "strict"; ProtectControlGroups = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; #PrivateDevices = true; #PrivateTmp = true; #PrivateUsers = true; #TemporaryFileSystem = ["/"]; #DynamicUser = true; RuntimeDirectory = "pxe-store-upload"; WorkingDirectory = "/run/pxe-store-upload"; }; }; }; sockets = { pxe-store-upload = { after = ["network-online.target"]; wants = ["network-online.target"]; wantedBy = ["sockets.target"]; socketConfig = { ListenDatagram = "[${cfg.linkLocal6}]:1792%%${cfg.network}"; }; }; }; }; }; }