nixos/preload: init
[NixPkgs.git] / nixos / modules / installer / netboot / netboot.nix
bloba50f22cbe471d0d6d72d18e4040cf632709b7b08
1 # This module creates netboot media containing the given NixOS
2 # configuration.
4 { config, lib, pkgs, ... }:
6 with lib;
9   options = {
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     };
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     };
33   };
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;
40     # !!! Hack - attributes expected by other modules.
41     environment.systemPackages = [ pkgs.grub2_efi ]
42       ++ (lib.optionals (pkgs.stdenv.hostPlatform.system != "aarch64-linux") [pkgs.grub2 pkgs.syslinux]);
44     fileSystems."/" = mkImageMediaOverride
45       { fsType = "tmpfs";
46         options = [ "mode=0755" ];
47       };
49     # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
50     # image) to make this a live CD.
51     fileSystems."/nix/.ro-store" = mkImageMediaOverride
52       { fsType = "squashfs";
53         device = "../nix-store.squashfs";
54         options = [ "loop" ];
55         neededForBoot = true;
56       };
58     fileSystems."/nix/.rw-store" = mkImageMediaOverride
59       { fsType = "tmpfs";
60         options = [ "mode=0755" ];
61         neededForBoot = true;
62       };
64     fileSystems."/nix/store" = mkImageMediaOverride
65       { fsType = "overlay";
66         device = "overlay";
67         options = [
68           "lowerdir=/nix/.ro-store"
69           "upperdir=/nix/.rw-store/store"
70           "workdir=/nix/.rw-store/work"
71         ];
73         depends = [
74           "/nix/.ro-store"
75           "/nix/.rw-store/store"
76           "/nix/.rw-store/work"
77         ];
78       };
80     boot.initrd.availableKernelModules = [ "squashfs" "overlay" ];
82     boot.initrd.kernelModules = [ "loop" "overlay" ];
84     # Closures to be copied to the Nix store, namely the init
85     # script and the top-level system configuration directory.
86     netboot.storeContents =
87       [ config.system.build.toplevel ];
89     # Create the squashfs image that contains the Nix store.
90     system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
91       storeContents = config.netboot.storeContents;
92       comp = config.netboot.squashfsCompression;
93     };
96     # Create the initrd
97     system.build.netbootRamdisk = pkgs.makeInitrdNG {
98       inherit (config.boot.initrd) compressor;
99       prepend = [ "${config.system.build.initialRamdisk}/initrd" ];
101       contents =
102         [ { object = config.system.build.squashfsStore;
103             symlink = "/nix-store.squashfs";
104           }
105         ];
106     };
108     system.build.netbootIpxeScript = pkgs.writeTextDir "netboot.ipxe" ''
109       #!ipxe
110       # Use the cmdline variable to allow the user to specify custom kernel params
111       # when chainloading this script from other iPXE scripts like netboot.xyz
112       kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ${toString config.boot.kernelParams} ''${cmdline}
113       initrd initrd
114       boot
115     '';
117     # A script invoking kexec on ./bzImage and ./initrd.gz.
118     # Usually used through system.build.kexecTree, but exposed here for composability.
119     system.build.kexecScript = pkgs.writeScript "kexec-boot" ''
120       #!/usr/bin/env bash
121       if ! kexec -v >/dev/null 2>&1; then
122         echo "kexec not found: please install kexec-tools" 2>&1
123         exit 1
124       fi
125       SCRIPT_DIR=$( cd -- "$( dirname -- "''${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
126       kexec --load ''${SCRIPT_DIR}/bzImage \
127         --initrd=''${SCRIPT_DIR}/initrd.gz \
128         --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}"
129       kexec -e
130     '';
132     # A tree containing initrd.gz, bzImage and a kexec-boot script.
133     system.build.kexecTree = pkgs.linkFarm "kexec-tree" [
134       {
135         name = "initrd.gz";
136         path = "${config.system.build.netbootRamdisk}/initrd";
137       }
138       {
139         name = "bzImage";
140         path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
141       }
142       {
143         name = "kexec-boot";
144         path = config.system.build.kexecScript;
145       }
146     ];
148     boot.loader.timeout = 10;
150     boot.postBootCommands =
151       ''
152         # After booting, register the contents of the Nix store
153         # in the Nix database in the tmpfs.
154         ${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
156         # nixos-rebuild also requires a "system" profile and an
157         # /etc/NIXOS tag.
158         touch /etc/NIXOS
159         ${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
160       '';
162   };