1 # This module creates netboot media containing the given NixOS
4 { config, lib, pkgs, ... }:
11 netboot.squashfsCompression = mkOption {
12 default = "zstd -Xcompression-level 19";
14 Compression settings to use for the squashfs nix store.
16 example = "zstd -Xcompression-level 6";
20 netboot.storeContents = mkOption {
21 example = literalExpression "[ pkgs.stdenv ]";
23 This option lists additional derivations to be included in the
24 Nix store in the generated netboot image.
31 # Don't build the GRUB menu builder script, since we don't need it
32 # here and it causes a cyclic dependency.
33 boot.loader.grub.enable = false;
35 fileSystems."/" = mkImageMediaOverride
37 options = [ "mode=0755" ];
40 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
41 # image) to make this a live CD.
42 fileSystems."/nix/.ro-store" = mkImageMediaOverride
43 { fsType = "squashfs";
44 device = "../nix-store.squashfs";
45 options = [ "loop" ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi";
49 fileSystems."/nix/.rw-store" = mkImageMediaOverride
51 options = [ "mode=0755" ];
55 fileSystems."/nix/store" = mkImageMediaOverride
57 lowerdir = [ "/nix/.ro-store" ];
58 upperdir = "/nix/.rw-store/store";
59 workdir = "/nix/.rw-store/work";
64 boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
66 boot.initrd.kernelModules = [ "loop" "overlay" ];
68 # Closures to be copied to the Nix store, namely the init
69 # script and the top-level system configuration directory.
70 netboot.storeContents =
71 [ config.system.build.toplevel ];
73 # Create the squashfs image that contains the Nix store.
74 system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
75 storeContents = config.netboot.storeContents;
76 comp = config.netboot.squashfsCompression;
81 system.build.netbootRamdisk = pkgs.makeInitrdNG {
82 inherit (config.boot.initrd) compressor;
83 prepend = [ "${config.system.build.initialRamdisk}/initrd" ];
86 [ { source = config.system.build.squashfsStore;
87 target = "/nix-store.squashfs";
92 system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
94 # Use the cmdline variable to allow the user to specify custom kernel params
95 # when chainloading this script from other iPXE scripts like netboot.xyz
96 kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
101 # A script invoking kexec on ./bzImage and ./initrd.gz.
102 # Usually used through system.build.kexecTree, but exposed here for composability.
103 system.build.kexecScript = pkgs.writeScript "kexec-boot" ''
105 if ! kexec -v >/dev/null 2>&1; then
106 echo "kexec not found: please install kexec-tools" 2>&1
109 SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
110 kexec --load ''${SCRIPT_DIR}/bzImage \
111 --initrd=''${SCRIPT_DIR}/initrd.gz \
112 --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
116 # A tree containing initrd.gz, bzImage and a kexec-boot script.
117 system.build.kexecTree = pkgs.linkFarm "kexec-tree" [
120 path = "${config.system.build.netbootRamdisk}/initrd";
124 path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
128 path = config.system.build.kexecScript;
132 boot.loader.timeout = 10;
134 boot.postBootCommands =
136 # After booting, register the contents of the Nix store
137 # in the Nix database in the tmpfs.
138 ${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
140 # nixos-rebuild also requires a "system" profile and an
143 ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system