nixpkgs-suyu/nixos/modules/installer/netboot/netboot.nix
Alyssa Ross e5e49df7fd
nixos/netboot: add squashfsCompression option
This is copied from isoImage.squashfsCompression.  It's useful to be
able to customise, as iteration cycles are very slow with xz, and
subjectively systems booted with less efficiently compressed squashfs
stores appear to have faster reads (although I didn't test that
scientificly so there could be other factors).
2023-05-09 14:15:10 +00:00

166 lines
5.3 KiB
Nix

# This module creates netboot media containing the given NixOS
# configuration.
{ config, lib, pkgs, ... }:
with lib;
{
options = {
netboot.squashfsCompression = mkOption {
default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% "
+ lib.optionalString isx86 "-Xbcj x86"
# Untested but should also reduce size for these platforms
+ lib.optionalString isAarch "-Xbcj arm"
+ lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc"
+ lib.optionalString (isSparc) "-Xbcj sparc";
description = lib.mdDoc ''
Compression settings to use for the squashfs nix store.
'';
example = "zstd -Xcompression-level 6";
type = types.str;
};
netboot.storeContents = mkOption {
example = literalExpression "[ pkgs.stdenv ]";
description = lib.mdDoc ''
This option lists additional derivations to be included in the
Nix store in the generated netboot image.
'';
};
};
config = {
# Don't build the GRUB menu builder script, since we don't need it
# here and it causes a cyclic dependency.
boot.loader.grub.enable = false;
# !!! Hack - attributes expected by other modules.
environment.systemPackages = [ pkgs.grub2_efi ]
++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux"
then []
else [ pkgs.grub2 pkgs.syslinux ]);
fileSystems."/" = mkImageMediaOverride
{ fsType = "tmpfs";
options = [ "mode=0755" ];
};
# In stage 1, mount a tmpfs on top of /nix/store (the squashfs
# image) to make this a live CD.
fileSystems."/nix/.ro-store" = mkImageMediaOverride
{ fsType = "squashfs";
device = "../nix-store.squashfs";
options = [ "loop" ];
neededForBoot = true;
};
fileSystems."/nix/.rw-store" = mkImageMediaOverride
{ fsType = "tmpfs";
options = [ "mode=0755" ];
neededForBoot = true;
};
fileSystems."/nix/store" = mkImageMediaOverride
{ fsType = "overlay";
device = "overlay";
options = [
"lowerdir=/nix/.ro-store"
"upperdir=/nix/.rw-store/store"
"workdir=/nix/.rw-store/work"
];
depends = [
"/nix/.ro-store"
"/nix/.rw-store/store"
"/nix/.rw-store/work"
];
};
boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
boot.initrd.kernelModules = [ "loop" "overlay" ];
# Closures to be copied to the Nix store, namely the init
# script and the top-level system configuration directory.
netboot.storeContents =
[ config.system.build.toplevel ];
# Create the squashfs image that contains the Nix store.
system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
storeContents = config.netboot.storeContents;
comp = config.netboot.squashfsCompression;
};
# Create the initrd
system.build.netbootRamdisk = pkgs.makeInitrdNG {
inherit (config.boot.initrd) compressor;
prepend = [ "${config.system.build.initialRamdisk}/initrd" ];
contents =
[ { object = config.system.build.squashfsStore;
symlink = "/nix-store.squashfs";
}
];
};
system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
#!ipxe
# Use the cmdline variable to allow the user to specify custom kernel params
# when chainloading this script from other iPXE scripts like netboot.xyz
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
initrd initrd
boot
'';
# A script invoking kexec on ./bzImage and ./initrd.gz.
# Usually used through system.build.kexecTree, but exposed here for composability.
system.build.kexecScript = pkgs.writeScript "kexec-boot" ''
#!/usr/bin/env bash
if ! kexec -v >/dev/null 2>&1; then
echo "kexec not found: please install kexec-tools" 2>&1
exit 1
fi
SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
kexec --load ''${SCRIPT_DIR}/bzImage \
--initrd=''${SCRIPT_DIR}/initrd.gz \
--command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
kexec -e
'';
# A tree containing initrd.gz, bzImage and a kexec-boot script.
system.build.kexecTree = pkgs.linkFarm "kexec-tree" [
{
name = "initrd.gz";
path = "${config.system.build.netbootRamdisk}/initrd";
}
{
name = "bzImage";
path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
}
{
name = "kexec-boot";
path = config.system.build.kexecScript;
}
];
boot.loader.timeout = 10;
boot.postBootCommands =
''
# After booting, register the contents of the Nix store
# in the Nix database in the tmpfs.
${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
# nixos-rebuild also requires a "system" profile and an
# /etc/NIXOS tag.
touch /etc/NIXOS
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
};
}