e5e49df7fd
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).
166 lines
5.3 KiB
Nix
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
|
|
'';
|
|
|
|
};
|
|
|
|
}
|