135 lines
4.1 KiB
Nix
135 lines
4.1 KiB
Nix
# This module creates netboot media containing the given NixOS
|
|
# configuration.
|
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
inherit (lib) mkOption literalExample;
|
|
netbootpkgs = pkgs.callPackage ./pkgs {};
|
|
in
|
|
|
|
{
|
|
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;
|
|
|
|
# make testing faster
|
|
boot.initrd.compressor = "gzip -9n";
|
|
|
|
# !!! 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."/" =
|
|
{
|
|
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" = {
|
|
fsType = "tmpfs";
|
|
options = [ "mode=0755" ];
|
|
neededForBoot = true;
|
|
};
|
|
|
|
boot.initrd = {
|
|
|
|
postMountCommands = ''
|
|
echo "Mounting initial store"
|
|
(
|
|
set -eux
|
|
mkdir -p /mnt-root/nix/.squash
|
|
mkdir -p /mnt-root/nix/store
|
|
|
|
gunzip < /nix-store-squashes/registration.gz > /mnt-root/nix/registration
|
|
|
|
# the manifest splits the /nix/store/.... path with a " " to
|
|
# prevent Nix from determining it depends on things.
|
|
for f in $(cat /nix-store-squashes/squashes | sed 's/ //'); do
|
|
prefix=$(basename "$(dirname "$f")")
|
|
suffix=$(basename "$f")
|
|
dest="$prefix$suffix"
|
|
mkdir "/mnt-root/nix/.squash/$dest"
|
|
mount -t squashfs -o loop "$f" "/mnt-root/nix/.squash/$dest"
|
|
(
|
|
# Ideally, these would not be copied and the mounts would be
|
|
# used directly. However, we can't: systemd tries to unmount
|
|
# them all at shutdown and gets stuck. The trade-off here is
|
|
# an increased RAM requirement and a slightly slower
|
|
# start-up. However, all that is much faster than needing
|
|
# to recreate the entire squashfs every time.
|
|
cd /mnt-root/nix/store/
|
|
cp -ar "../.squash/$dest/$dest" "./$dest"
|
|
)
|
|
umount "/mnt-root/nix/.squash/$dest"
|
|
rm "$f"
|
|
set +x
|
|
done
|
|
)
|
|
'';
|
|
|
|
availableKernelModules = [ "squashfs" "overlay" ];
|
|
kernelModules = [ "loop" "overlay" ];
|
|
};
|
|
|
|
# Create the squashfs image that contains the Nix store.
|
|
system.build.squashfsStore = netbootpkgs.makeSquashfsManifest {
|
|
name = "iso-manifest";
|
|
storeContents = config.system.build.toplevel;
|
|
};
|
|
|
|
system.build.ipxeBootDir = netbootpkgs.makePxeScript {
|
|
inherit config pkgs;
|
|
initrds = {
|
|
initrd = "${config.system.build.initialRamdisk}/initrd";
|
|
|
|
# squashfsStore is just a manifest file, and makeCpioRecursive
|
|
# will bring in all its dependencies automatically.
|
|
# the nix-store initrd is the actual files, and the manifest
|
|
# is intentionally only just the manifest file, located
|
|
# at /nix-store-isos
|
|
nix-store = "${(
|
|
netbootpkgs.makeCpioRecursive {
|
|
name = "better-initrd";
|
|
inherit (config.boot.initrd) compressor;
|
|
root = config.system.build.squashfsStore;
|
|
}
|
|
)}/initrd";
|
|
manifest = "${pkgs.makeInitrd {
|
|
inherit (config.boot.initrd) compressor;
|
|
contents =
|
|
[
|
|
{
|
|
object = config.system.build.squashfsStore.manifest;
|
|
symlink = "/nix-store-squashes";
|
|
}
|
|
];
|
|
}}/initrd";
|
|
};
|
|
};
|
|
|
|
boot.loader.timeout = 10;
|
|
|
|
boot.postBootCommands =
|
|
''
|
|
# After booting, register the contents of the Nix store
|
|
# in the Nix database in the tmpfs.
|
|
echo "Loading the Nix database"
|
|
${config.nix.package}/bin/nix-store --load-db < /nix/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
|
|
'';
|
|
|
|
};
|
|
|
|
} |