nixos: Initial netbooting installer
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 34m36s
Installer / Build installer (push) Successful in 4m34s

This commit is contained in:
2024-06-24 00:08:55 +01:00
parent 9f2651e352
commit 84ca556c47
9 changed files with 390 additions and 16 deletions

View File

@@ -1,6 +1,6 @@
{ lib, pkgs, extendModules, modulesPath, options, config, ... }:
let
inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge flatten optional;
inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge mkForce flatten optional;
inherit (lib.my) mkBoolOpt' dummyOption;
cfg = config.my.build;
@@ -43,15 +43,144 @@ let
modules = flatten [
"${modulesPath}/installer/netboot/netboot.nix"
allHardware
];
};
asNetboot = extendModules {
modules = flatten [
allHardware
({ pkgs, config, ... }: {
system.build.netbootArchive = pkgs.runCommand "netboot-${config.system.name}-archive.tar" { } ''
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.kernel}" \
-f "$out" "${config.system.boot.loader.kernelFile}"
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootRamdisk}" \
-f "$out" initrd
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootIpxeScript}" \
-f "$out" netboot.ipxe
'';
boot = {
loader.grub.enable = false;
initrd = {
kernelModules = [ "nbd" ];
systemd = {
storePaths = with pkgs; [
gnused
nbd
netcat
];
extraBin = with pkgs; {
dmesg = "${util-linux}/bin/dmesg";
ip = "${iproute2}/bin/ip";
nbd-client = "${nbd}/bin/nbd-client";
};
extraConfig = ''
DefaultTimeoutStartSec=10
DefaultDeviceTimeoutSec=10
'';
network = {
enable = true;
wait-online.enable = true;
networks."10-netboot" = {
matchConfig.Name = "et-boot";
DHCP = "yes";
};
};
services = {
nbd = {
description = "NBD Root FS";
script = ''
get_cmdline() {
${pkgs.gnused}/bin/sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
}
s="$(get_cmdline nbd_server)"
until ${pkgs.netcat}/bin/nc -zv "$s" 22; do
sleep 0.1
done
exec ${pkgs.nbd}/bin/nbd-client -systemd-mark -N "$(get_cmdline nbd_export)" "$s" /dev/nbd0
'';
unitConfig = {
IgnoreOnIsolate = "yes";
DefaultDependencies = "no";
};
serviceConfig = {
Type = "forking";
Restart = "on-failure";
RestartSec = 10;
};
wantedBy = [ "initrd-root-device.target" ];
};
};
};
};
postBootCommands = ''
# After booting, register the contents of the Nix store
# in the Nix database in the COW root.
${config.nix.package}/bin/nix-store --load-db < /nix-path-registration
# nixos-rebuild also requires a "system" profile and an
# /etc/NIXOS tag.
touch /etc/NIXOS
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
};
programs.nbd.enable = true;
fileSystems = {
"/" = {
fsType = "ext4";
device = "/dev/nbd0";
noCheck = true;
autoResize = true;
};
};
networking.useNetworkd = mkForce true;
systemd = {
network.networks."10-boot" = {
matchConfig.Name = "et-boot";
DHCP = "yes";
networkConfig.KeepConfiguration = "yes";
};
};
system.build = {
rootImage = pkgs.callPackage "${modulesPath}/../lib/make-ext4-fs.nix" {
storePaths = [ config.system.build.toplevel ];
volumeLabel = "netboot-root";
};
netbootScript = pkgs.writeText "boot.ipxe" ''
#!ipxe
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ifname=et-boot:''${mac} nbd_server=''${next-server} ${toString config.boot.kernelParams} ''${cmdline}
initrd initrd
boot
'';
netbootTree = pkgs.linkFarm "netboot-${config.system.name}" [
{
name = config.system.boot.loader.kernelFile;
path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
}
{
name = "initrd";
path = "${config.system.build.initialRamdisk}/initrd";
}
{
name = "rootfs.ext4";
path = config.system.build.rootImage;
}
{
name = "boot.ipxe";
path = config.system.build.netbootScript;
}
];
netbootArchive = pkgs.runCommand "netboot-${config.system.name}.tar.zst" { } ''
export PATH=${pkgs.zstd}/bin:$PATH
${pkgs.gnutar}/bin/tar --dereference --zstd -cvC ${config.system.build.netbootTree} -f "$out" .
'';
};
})
];
};
@@ -77,6 +206,7 @@ in
asISO = mkAsOpt asISO "a bootable .iso image";
asContainer = mkAsOpt asContainer "a container";
asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
asNetboot = mkAsOpt asNetboot "a netboot-able kernel initrd, and iPXE script";
buildAs = options.system.build;
};
@@ -110,7 +240,8 @@ in
iso = config.my.asISO.config.system.build.isoImage;
container = config.my.asContainer.config.system.build.toplevel;
kexecTree = config.my.asKexecTree.config.system.build.kexecTree;
netbootArchive = config.my.asKexecTree.config.system.build.netbootArchive;
netbootTree = config.my.asNetboot.config.system.build.netbootTree;
netbootArchive = config.my.asNetboot.config.system.build.netbootArchive;
};
};
};