1 # This module creates a bootable ISO image containing the given NixOS
2 # configuration. The derivation for the ISO image will be placed in
3 # config.system.build.isoImage.
5 { config, lib, pkgs, ... }:
11 * Given a list of `options`, concats the result of mapping each options
12 * to a menuentry for use in grub.
14 * * defaults: {name, image, params, initrd}
15 * * options: [ option... ]
16 * * option: {name, params, class}
19 defaults: options: lib.concatStrings
23 menuentry '${defaults.name} ${
24 # Name appended to menuentry defaults to params if no specific name given.
25 option.name or (optionalString (option ? params) "(${option.params})")
26 }' ${optionalString (option ? class) " --class ${option.class}"} {
27 # Fallback to UEFI console for boot, efifb sometimes has difficulties.
28 terminal_output console
30 linux ${defaults.image} \''${isoboot} ${defaults.params} ${
33 initrd ${defaults.initrd}
41 * Builds the default options.
43 buildMenuGrub2 = buildMenuAdditionalParamsGrub2 "";
46 if config.boot.loader.grub.forcei686 then
49 pkgs.stdenv.hostPlatform.efiArch;
52 * Given params to add to `params`, build a set of default options.
53 * Use this one when creating a variant (e.g. hidpi)
55 buildMenuAdditionalParamsGrub2 = additional:
58 name = "${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}";
59 params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}";
60 image = "/boot/${config.system.boot.loader.kernelFile}";
61 initrd = "/boot/initrd";
68 { class = "installer"; }
69 { class = "nomodeset"; params = "nomodeset"; }
70 { class = "copytoram"; params = "copytoram"; }
71 { class = "debug"; params = "debug"; }
75 # Timeout in syslinux is in units of 1/10 of a second.
76 # null means max timeout (35996, just under 1h in 1/10 seconds)
77 # 0 means disable timeout
78 syslinuxTimeout = if config.boot.loader.timeout == null then
81 config.boot.loader.timeout * 10;
83 # Timeout in grub is in seconds.
84 # null means max timeout (infinity)
85 # 0 means disable timeout
86 grubEfiTimeout = if config.boot.loader.timeout == null then
89 config.boot.loader.timeout;
91 # The configuration file for syslinux.
93 # Notes on syslinux configuration and UNetbootin compatibility:
94 # * Do not use '/syslinux/syslinux.cfg' as the path for this
95 # configuration. UNetbootin will not parse the file and use it as-is.
96 # This results in a broken configuration if the partition label does
97 # not match the specified config.isoImage.volumeID. For this reason
98 # we're using '/isolinux/isolinux.cfg'.
99 # * Use APPEND instead of adding command-line arguments directly after
101 # * COM32 entries (chainload, reboot, poweroff) are not recognized. They
102 # result in incorrect boot entries.
106 TIMEOUT ${builtins.toString syslinuxTimeout}
108 MENU BACKGROUND /isolinux/background.png
110 ${config.isoImage.syslinuxTheme}
115 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
116 LINUX /boot/${config.system.boot.loader.kernelFile}
117 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
118 INITRD /boot/${config.system.boot.loader.initrdFile}
120 # A variant to boot with 'nomodeset'
122 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset)
123 LINUX /boot/${config.system.boot.loader.kernelFile}
124 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
125 INITRD /boot/${config.system.boot.loader.initrdFile}
127 # A variant to boot with 'copytoram'
129 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram)
130 LINUX /boot/${config.system.boot.loader.kernelFile}
131 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
132 INITRD /boot/${config.system.boot.loader.initrdFile}
134 # A variant to boot with verbose logging to the console
136 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
137 LINUX /boot/${config.system.boot.loader.kernelFile}
138 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
139 INITRD /boot/${config.system.boot.loader.initrdFile}
141 # A variant to boot with a serial console enabled
143 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8)
144 LINUX /boot/${config.system.boot.loader.kernelFile}
145 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0,115200n8
146 INITRD /boot/${config.system.boot.loader.initrdFile}
149 isolinuxMemtest86Entry = ''
151 MENU LABEL Memtest86+
152 LINUX /boot/memtest.bin
153 APPEND ${toString config.boot.loader.grub.memtest86.params}
156 isolinuxCfg = concatStringsSep "\n"
157 ([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
159 refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null;
161 # Setup instructions for rEFInd.
163 if refindBinary != null then
165 # Adds rEFInd to the ISO.
166 cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/boot/
169 "# No refind for ${targetArch}"
172 grubPkgs = if config.boot.loader.grub.forcei686 then pkgs.pkgsi686Linux else pkgs;
179 # Search using a "marker file"
180 search --set=root --file /EFI/nixos-installer-image
185 set gfxmode=${concatStringsSep "," [
186 # GRUB will use the first valid mode listed here.
187 # `auto` will sometimes choose the smallest valid mode it detects.
188 # So instead we'll list a lot of possibly valid modes :/
203 if [ "\$textmode" == "false" ]; then
204 terminal_output gfxterm
205 terminal_input console
207 terminal_output console
208 terminal_input console
209 # Sets colors for console term.
210 set menu_color_normal=cyan/blue
211 set menu_color_highlight=white/blue
214 ${ # When there is a theme configured, use it, otherwise use the background image.
215 if config.isoImage.grubTheme != null then ''
217 set theme=(\$root)/EFI/boot/grub-theme/theme.txt
219 $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
221 if background_image (\$root)/EFI/boot/efi-background.png; then
222 # Black background means transparent background when there
223 # is a background image set... This seems undocumented :(
224 set color_normal=black/black
225 set color_highlight=white/blue
227 # Falls back again to proper colors.
228 set menu_color_normal=cyan/blue
229 set menu_color_highlight=white/blue
234 # The EFI boot image.
236 # * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you
237 # will get white-on-black console-like text on sub-menus. *sigh*
238 efiDir = pkgs.runCommand "efi-directory" {
239 nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ];
242 mkdir -p $out/EFI/boot/
244 # Add a marker so GRUB can find the filesystem.
245 touch $out/EFI/nixos-installer-image
247 # ALWAYS required modules.
249 # Basic modules for filesystems and partition schemes
264 # Allows rebooting into firmware setup interface
267 # EFI Graphics Output Protocol
280 # We're not using it anymore, but we'll leave it in so it can be used
281 # by user, with the console using "C"
284 # Graphical mode stuff
294 # File types for graphical mode
298 echo "Building GRUB with modules:"
299 for mod in ''${MODULES[@]}; do
303 # Modules that may or may not be available per-platform.
304 echo "Adding additional modules:"
305 for mod in efi_uga; do
306 if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then
312 # Make our own efi program, we can't rely on "grub-install" since it seems to
313 # probe for devices, even with --skip-fs-probe.
315 --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} \
316 -o $out/EFI/boot/boot${targetArch}.efi \
318 -O ${grubPkgs.grub2_efi.grubTarget} \
320 cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
322 cat <<EOF > $out/EFI/boot/grub.cfg
324 set textmode=${boolToString (config.isoImage.forceTextMode)}
325 set timeout=${toString grubEfiTimeout}
328 # This message will only be viewable on the default (UEFI) console.
330 echo "Loading graphical boot menu..."
332 echo "Press 't' to use the text boot menu on this console..."
337 hiddenentry 'Text mode' --hotkey 't' {
338 loadfont (\$root)/EFI/boot/unicode.pf2
340 terminal_output console
342 hiddenentry 'GUI mode' --hotkey 'g' {
343 $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
345 terminal_output gfxterm
349 # If the parameter iso_path is set, append the findiso parameter to the kernel
350 # line. We need this to allow the nixos iso to be booted from grub directly.
351 if [ \''${iso_path} ] ; then
352 set isoboot="findiso=\''${iso_path}"
360 submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu {
362 submenu "Suggests resolution @720p" --class hidpi-720p {
364 ${buildMenuAdditionalParamsGrub2 "video=1280x720@60"}
366 submenu "Suggests resolution @1080p" --class hidpi-1080p {
368 ${buildMenuAdditionalParamsGrub2 "video=1920x1080@60"}
371 # If we boot into a graphical environment where X is autoran
372 # and always crashes, it makes the media unusable. Allow the user
374 submenu "Disable display-manager" --class quirk-disable-displaymanager {
376 ${buildMenuAdditionalParamsGrub2 "systemd.mask=display-manager.service"}
379 # Some laptop and convertibles have the panel installed in an
380 # inconvenient way, rotated away from the keyboard.
381 # Those entries makes it easier to use the installer.
383 submenu "Rotate framebuffer Clockwise" --class rotate-90cw {
385 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:1"}
387 submenu "Rotate framebuffer Upside-Down" --class rotate-180 {
389 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:2"}
391 submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw {
393 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:3"}
396 # As a proof of concept, mainly. (Not sure it has accessibility merits.)
398 submenu "Use black on white" --class accessibility-blakconwhite {
400 ${buildMenuAdditionalParamsGrub2 "vt.default_red=0xFF,0xBC,0x4F,0xB4,0x56,0xBC,0x4F,0x00,0xA1,0xCF,0x84,0xCA,0x8D,0xB4,0x84,0x68 vt.default_grn=0xFF,0x55,0xBA,0xBA,0x4D,0x4D,0xB3,0x00,0xA0,0x8F,0xB3,0xCA,0x88,0x93,0xA4,0x68 vt.default_blu=0xFF,0x58,0x5F,0x58,0xC5,0xBD,0xC5,0x00,0xA8,0xBB,0xAB,0x97,0xBD,0xC7,0xC5,0x68"}
403 # Serial access is a must!
405 submenu "Serial console=ttyS0,115200n8" --class serial {
407 ${buildMenuAdditionalParamsGrub2 "console=ttyS0,115200n8"}
411 ${lib.optionalString (refindBinary != null) ''
412 # GRUB apparently cannot do "chainloader" operations on "CD".
413 if [ "\$root" != "cd0" ]; then
414 menuentry 'rEFInd' --class refind {
415 # Force root to be the FAT partition
416 # Otherwise it breaks rEFInd's boot
417 search --set=root --no-floppy --fs-uuid 1234-5678
418 chainloader (\$root)/EFI/boot/${refindBinary}
422 menuentry 'Firmware Setup' --class settings {
426 echo "If you see this message, your EFI system doesn't support this feature."
429 menuentry 'Shutdown' --class shutdown {
434 grub-script-check $out/EFI/boot/grub.cfg
439 efiImg = pkgs.runCommand "efi-image_eltorito" {
440 nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
443 # Be careful about determinism: du --apparent-size,
444 # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
446 mkdir ./contents && cd ./contents
448 cp -rp "${efiDir}"/EFI/boot/{grub.cfg,*.efi} ./EFI/boot
450 # Rewrite dates for everything in the FS
451 find . -exec touch --date=2000-01-01 {} +
453 # Round up to the nearest multiple of 1MB, for more deterministic du output
454 usage_size=$(( $(du -s --block-size=1M --apparent-size . | tr -cd '[:digit:]') * 1024 * 1024 ))
455 # Make the image 110% as big as the files need to make up for FAT overhead
456 image_size=$(( ($usage_size * 110) / 100 ))
457 # Make the image fit blocks of 1M
458 block_size=$((1024*1024))
459 image_size=$(( ($image_size / $block_size + 1) * $block_size ))
460 echo "Usage size: $usage_size"
461 echo "Image size: $image_size"
462 truncate --size=$image_size "$out"
463 mkfs.vfat --invariant -i 12345678 -n EFIBOOT "$out"
465 # Force a fixed order in mcopy for better determinism, and avoid file globbing
466 for d in $(find EFI -type d | sort); do
467 faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d"
470 for f in $(find EFI -type f | sort); do
471 mcopy -pvm -i "$out" "$f" "::/$f"
474 # Verify the FAT partition.
483 isoImage.isoName = mkOption {
484 default = "${config.isoImage.isoBaseName}.iso";
485 type = lib.types.str;
486 description = lib.mdDoc ''
487 Name of the generated ISO image file.
491 isoImage.isoBaseName = mkOption {
492 default = config.system.nixos.distroId;
493 type = lib.types.str;
494 description = lib.mdDoc ''
495 Prefix of the name of the generated ISO image file.
499 isoImage.compressImage = mkOption {
501 type = lib.types.bool;
502 description = lib.mdDoc ''
503 Whether the ISO image should be compressed using
508 isoImage.squashfsCompression = mkOption {
509 default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% "
510 + lib.optionalString isx86 "-Xbcj x86"
511 # Untested but should also reduce size for these platforms
512 + lib.optionalString isAarch "-Xbcj arm"
513 + lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc"
514 + lib.optionalString (isSparc) "-Xbcj sparc";
515 type = lib.types.str;
516 description = lib.mdDoc ''
517 Compression settings to use for the squashfs nix store.
519 example = "zstd -Xcompression-level 6";
522 isoImage.edition = mkOption {
524 type = lib.types.str;
525 description = lib.mdDoc ''
526 Specifies which edition string to use in the volume ID of the generated
531 isoImage.volumeID = mkOption {
532 # nixos-$EDITION-$RELEASE-$ARCH
533 default = "nixos${optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
534 type = lib.types.str;
535 description = lib.mdDoc ''
536 Specifies the label or volume ID of the generated ISO image.
537 Note that the label is used by stage 1 of the boot process to
538 mount the CD, so it should be reasonably distinctive.
542 isoImage.contents = mkOption {
543 example = literalExpression ''
544 [ { source = pkgs.memtest86 + "/memtest.bin";
545 target = "boot/memtest.bin";
549 description = lib.mdDoc ''
550 This option lists files to be copied to fixed locations in the
555 isoImage.storeContents = mkOption {
556 example = literalExpression "[ pkgs.stdenv ]";
557 description = lib.mdDoc ''
558 This option lists additional derivations to be included in the
559 Nix store in the generated ISO image.
563 isoImage.includeSystemBuildDependencies = mkOption {
565 type = lib.types.bool;
566 description = lib.mdDoc ''
567 Set this option to include all the needed sources etc in the
568 image. It significantly increases image size. Use that when
569 you want to be able to keep all the sources needed to build your
570 system or when you are going to install the system on a computer
571 with slow or non-existent network connection.
575 isoImage.makeBiosBootable = mkOption {
576 # Before this option was introduced, images were BIOS-bootable if the
577 # hostPlatform was x86-based. This option is enabled by default for
578 # backwards compatibility.
580 # Also note that syslinux package currently cannot be cross-compiled from
581 # non-x86 platforms, so the default is false on non-x86 build platforms.
582 default = pkgs.stdenv.buildPlatform.isx86 && pkgs.stdenv.hostPlatform.isx86;
583 defaultText = lib.literalMD ''
584 `true` if both build and host platforms are x86-based architectures,
585 e.g. i686 and x86_64.
587 type = lib.types.bool;
588 description = lib.mdDoc ''
589 Whether the ISO image should be a BIOS-bootable disk.
593 isoImage.makeEfiBootable = mkOption {
595 type = lib.types.bool;
596 description = lib.mdDoc ''
597 Whether the ISO image should be an EFI-bootable volume.
601 isoImage.makeUsbBootable = mkOption {
603 type = lib.types.bool;
604 description = lib.mdDoc ''
605 Whether the ISO image should be bootable from CD as well as USB.
609 isoImage.efiSplashImage = mkOption {
610 default = pkgs.fetchurl {
611 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png";
612 sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x";
614 description = lib.mdDoc ''
615 The splash image to use in the EFI bootloader.
619 isoImage.splashImage = mkOption {
620 default = pkgs.fetchurl {
621 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png";
622 sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd";
624 description = lib.mdDoc ''
625 The splash image to use in the legacy-boot bootloader.
629 isoImage.grubTheme = mkOption {
630 default = pkgs.nixos-grub2-theme;
631 type = types.nullOr (types.either types.path types.package);
632 description = lib.mdDoc ''
633 The grub2 theme used for UEFI boot.
637 isoImage.syslinuxTheme = mkOption {
639 MENU TITLE ${config.system.nixos.distroName}
640 MENU RESOLUTION 800 600
647 MENU HELPMSGENDROW -1
650 # FG:AARRGGBB BG:AARRGGBB shadow
651 MENU COLOR BORDER 30;44 #00000000 #00000000 none
652 MENU COLOR SCREEN 37;40 #FF000000 #00E2E8FF none
653 MENU COLOR TABMSG 31;40 #80000000 #00000000 none
654 MENU COLOR TIMEOUT 1;37;40 #FF000000 #00000000 none
655 MENU COLOR TIMEOUT_MSG 37;40 #FF000000 #00000000 none
656 MENU COLOR CMDMARK 1;36;40 #FF000000 #00000000 none
657 MENU COLOR CMDLINE 37;40 #FF000000 #00000000 none
658 MENU COLOR TITLE 1;36;44 #00000000 #00000000 none
659 MENU COLOR UNSEL 37;44 #FF000000 #00000000 none
660 MENU COLOR SEL 7;37;40 #FFFFFFFF #FF5277C3 std
663 description = lib.mdDoc ''
664 The syslinux theme used for BIOS boot.
668 isoImage.prependToMenuLabel = mkOption {
671 example = "Install ";
672 description = lib.mdDoc ''
673 The string to prepend before the menu label for the NixOS system.
674 This will be directly prepended (without whitespace) to the NixOS version
675 string, like for example if it is set to `XXX`:
677 `XXXNixOS 99.99-pre666`
681 isoImage.appendToMenuLabel = mkOption {
682 default = " Installer";
684 example = " Live System";
685 description = lib.mdDoc ''
686 The string to append after the menu label for the NixOS system.
687 This will be directly appended (without whitespace) to the NixOS version
688 string, like for example if it is set to `XXX`:
690 `NixOS 99.99-pre666XXX`
694 isoImage.forceTextMode = mkOption {
698 description = lib.mdDoc ''
699 Whether to use text mode instead of graphical grub.
700 A value of `true` means graphical mode is not tried to be used.
702 This is useful for validating that graphics mode usage is not at the root cause of a problem with the iso image.
704 If text mode is required off-handedly (e.g. for serial use) you can use the `T` key, after being prompted, to use text mode for the current boot.
710 # store them in lib so we can mkImageMediaOverride the
711 # entire file system layout in installation media (only)
712 config.lib.isoFileSystems = {
713 "/" = mkImageMediaOverride
716 options = [ "mode=0755" ];
719 # Note that /dev/root is a symlink to the actual root device
720 # specified on the kernel command line, created in the stage 1
722 "/iso" = mkImageMediaOverride
723 { device = "/dev/root";
724 neededForBoot = true;
728 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
729 # image) to make this a live CD.
730 "/nix/.ro-store" = mkImageMediaOverride
731 { fsType = "squashfs";
732 device = "/iso/nix-store.squashfs";
733 options = [ "loop" ];
734 neededForBoot = true;
737 "/nix/.rw-store" = mkImageMediaOverride
739 options = [ "mode=0755" ];
740 neededForBoot = true;
743 "/nix/store" = mkImageMediaOverride
744 { fsType = "overlay";
747 "lowerdir=/nix/.ro-store"
748 "upperdir=/nix/.rw-store/store"
749 "workdir=/nix/.rw-store/work"
753 "/nix/.rw-store/store"
754 "/nix/.rw-store/work"
762 # Syslinux (and isolinux) only supports x86-based architectures.
763 assertion = config.isoImage.makeBiosBootable -> pkgs.stdenv.hostPlatform.isx86;
764 message = "BIOS boot is only supported on x86-based architectures.";
767 assertion = !(stringLength config.isoImage.volumeID > 32);
768 # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
769 # Volume Identifier can only be 32 bytes
771 length = stringLength config.isoImage.volumeID;
772 howmany = toString length;
773 toomany = toString (length - 32);
775 "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32.";
779 # Don't build the GRUB menu builder script, since we don't need it
780 # here and it causes a cyclic dependency.
781 boot.loader.grub.enable = false;
783 environment.systemPackages = [ grubPkgs.grub2 grubPkgs.grub2_efi ]
784 ++ optional (config.isoImage.makeBiosBootable) pkgs.syslinux
787 # In stage 1 of the boot, mount the CD as the root FS by label so
788 # that we don't need to know its device. We pass the label of the
789 # root filesystem on the kernel command line, rather than in
790 # `fileSystems' below. This allows CD-to-USB converters such as
791 # UNetbootin to rewrite the kernel command line to pass the label or
792 # UUID of the USB stick. It would be nicer to write
793 # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't
796 [ "root=LABEL=${config.isoImage.volumeID}"
800 fileSystems = config.lib.isoFileSystems;
802 boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
804 boot.initrd.kernelModules = [ "loop" "overlay" ];
806 # Closures to be copied to the Nix store on the CD, namely the init
807 # script and the top-level system configuration directory.
808 isoImage.storeContents =
809 [ config.system.build.toplevel ] ++
810 optional config.isoImage.includeSystemBuildDependencies
811 config.system.build.toplevel.drvPath;
813 # Create the squashfs image that contains the Nix store.
814 system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
815 storeContents = config.isoImage.storeContents;
816 comp = config.isoImage.squashfsCompression;
819 # Individual files to be included on the CD, outside of the Nix
823 { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
824 target = "/boot/" + config.system.boot.loader.kernelFile;
826 { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
827 target = "/boot/" + config.system.boot.loader.initrdFile;
829 { source = config.system.build.squashfsStore;
830 target = "/nix-store.squashfs";
832 { source = pkgs.writeText "version" config.system.nixos.label;
833 target = "/version.txt";
835 ] ++ optionals (config.isoImage.makeBiosBootable) [
836 { source = config.isoImage.splashImage;
837 target = "/isolinux/background.png";
839 { source = pkgs.substituteAll {
840 name = "isolinux.cfg";
841 src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
844 target = "/isolinux/isolinux.cfg";
846 { source = "${pkgs.syslinux}/share/syslinux";
847 target = "/isolinux";
849 ] ++ optionals config.isoImage.makeEfiBootable [
851 target = "/boot/efi.img";
853 { source = "${efiDir}/EFI";
856 { source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/boot/grub.cfg") + "/grub";
857 target = "/boot/grub";
859 { source = config.isoImage.efiSplashImage;
860 target = "/EFI/boot/efi-background.png";
862 ] ++ optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [
863 { source = "${pkgs.memtest86plus}/memtest.bin";
864 target = "/boot/memtest.bin";
866 ] ++ optionals (config.isoImage.grubTheme != null) [
867 { source = config.isoImage.grubTheme;
868 target = "/EFI/boot/grub-theme";
872 boot.loader.timeout = 10;
874 # Create the ISO image.
875 system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({
876 inherit (config.isoImage) isoName compressImage volumeID contents;
877 bootable = config.isoImage.makeBiosBootable;
878 bootImage = "/isolinux/isolinux.bin";
879 syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null;
880 } // optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) {
882 isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
883 } // optionalAttrs config.isoImage.makeEfiBootable {
885 efiBootImage = "boot/efi.img";
888 boot.postBootCommands =
890 # After booting, register the contents of the Nix store on the
891 # CD in the Nix database in the tmpfs.
892 ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration
894 # nixos-rebuild also requires a "system" profile and an
897 ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
900 # Add vfat support to the initrd to enable people to copy the
901 # contents of the CD to a bootable USB stick.
902 boot.initrd.supportedFilesystems = [ "vfat" ];