at 23.11-pre 5.4 kB view raw
1# This module creates netboot media containing the given NixOS 2# configuration. 3 4{ config, lib, pkgs, ... }: 5 6with lib; 7 8{ 9 options = { 10 11 netboot.squashfsCompression = mkOption { 12 default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% " 13 + lib.optionalString isx86 "-Xbcj x86" 14 # Untested but should also reduce size for these platforms 15 + lib.optionalString isAarch "-Xbcj arm" 16 + lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc" 17 + lib.optionalString (isSparc) "-Xbcj sparc"; 18 description = lib.mdDoc '' 19 Compression settings to use for the squashfs nix store. 20 ''; 21 example = "zstd -Xcompression-level 6"; 22 type = types.str; 23 }; 24 25 netboot.storeContents = mkOption { 26 example = literalExpression "[ pkgs.stdenv ]"; 27 description = lib.mdDoc '' 28 This option lists additional derivations to be included in the 29 Nix store in the generated netboot image. 30 ''; 31 }; 32 33 }; 34 35 config = { 36 # Don't build the GRUB menu builder script, since we don't need it 37 # here and it causes a cyclic dependency. 38 boot.loader.grub.enable = false; 39 40 # !!! Hack - attributes expected by other modules. 41 environment.systemPackages = [ pkgs.grub2_efi ] 42 ++ (if pkgs.stdenv.hostPlatform.system == "aarch64-linux" 43 then [] 44 else [ pkgs.grub2 pkgs.syslinux ]); 45 46 fileSystems."/" = mkImageMediaOverride 47 { fsType = "tmpfs"; 48 options = [ "mode=0755" ]; 49 }; 50 51 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs 52 # image) to make this a live CD. 53 fileSystems."/nix/.ro-store" = mkImageMediaOverride 54 { fsType = "squashfs"; 55 device = "../nix-store.squashfs"; 56 options = [ "loop" ]; 57 neededForBoot = true; 58 }; 59 60 fileSystems."/nix/.rw-store" = mkImageMediaOverride 61 { fsType = "tmpfs"; 62 options = [ "mode=0755" ]; 63 neededForBoot = true; 64 }; 65 66 fileSystems."/nix/store" = mkImageMediaOverride 67 { fsType = "overlay"; 68 device = "overlay"; 69 options = [ 70 "lowerdir=/nix/.ro-store" 71 "upperdir=/nix/.rw-store/store" 72 "workdir=/nix/.rw-store/work" 73 ]; 74 75 depends = [ 76 "/nix/.ro-store" 77 "/nix/.rw-store/store" 78 "/nix/.rw-store/work" 79 ]; 80 }; 81 82 boot.initrd.availableKernelModules = [ "squashfs" "overlay" ]; 83 84 boot.initrd.kernelModules = [ "loop" "overlay" ]; 85 86 # Closures to be copied to the Nix store, namely the init 87 # script and the top-level system configuration directory. 88 netboot.storeContents = 89 [ config.system.build.toplevel ]; 90 91 # Create the squashfs image that contains the Nix store. 92 system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix { 93 storeContents = config.netboot.storeContents; 94 comp = config.netboot.squashfsCompression; 95 }; 96 97 98 # Create the initrd 99 system.build.netbootRamdisk = pkgs.makeInitrdNG { 100 inherit (config.boot.initrd) compressor; 101 prepend = [ "${config.system.build.initialRamdisk}/initrd" ]; 102 103 contents = 104 [ { object = config.system.build.squashfsStore; 105 symlink = "/nix-store.squashfs"; 106 } 107 ]; 108 }; 109 110 system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" '' 111 #!ipxe 112 # Use the cmdline variable to allow the user to specify custom kernel params 113 # when chainloading this script from other iPXE scripts like netboot.xyz 114 kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline} 115 initrd initrd 116 boot 117 ''; 118 119 # A script invoking kexec on ./bzImage and ./initrd.gz. 120 # Usually used through system.build.kexecTree, but exposed here for composability. 121 system.build.kexecScript = pkgs.writeScript "kexec-boot" '' 122 #!/usr/bin/env bash 123 if ! kexec -v >/dev/null 2>&1; then 124 echo "kexec not found: please install kexec-tools" 2>&1 125 exit 1 126 fi 127 SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) 128 kexec --load ''${SCRIPT_DIR}/bzImage \ 129 --initrd=''${SCRIPT_DIR}/initrd.gz \ 130 --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" 131 kexec -e 132 ''; 133 134 # A tree containing initrd.gz, bzImage and a kexec-boot script. 135 system.build.kexecTree = pkgs.linkFarm "kexec-tree" [ 136 { 137 name = "initrd.gz"; 138 path = "${config.system.build.netbootRamdisk}/initrd"; 139 } 140 { 141 name = "bzImage"; 142 path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}"; 143 } 144 { 145 name = "kexec-boot"; 146 path = config.system.build.kexecScript; 147 } 148 ]; 149 150 boot.loader.timeout = 10; 151 152 boot.postBootCommands = 153 '' 154 # After booting, register the contents of the Nix store 155 # in the Nix database in the tmpfs. 156 ${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration 157 158 # nixos-rebuild also requires a "system" profile and an 159 # /etc/NIXOS tag. 160 touch /etc/NIXOS 161 ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system 162 ''; 163 164 }; 165 166}