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.
4 { config, lib, pkgs, ... }:
7 * Given a list of `options`, concats the result of mapping each options
8 * to a menuentry for use in grub.
10 * * defaults: {name, image, params, initrd}
11 * * options: [ option... ]
12 * * option: {name, params, class}
15 defaults: options: lib.concatStrings
19 menuentry '${defaults.name} ${
20 # Name appended to menuentry defaults to params if no specific name given.
21 option.name or (lib.optionalString (option ? params) "(${option.params})")
22 }' ${lib.optionalString (option ? class) " --class ${option.class}"} {
23 # Fallback to UEFI console for boot, efifb sometimes has difficulties.
24 terminal_output console
26 linux ${defaults.image} \''${isoboot} ${defaults.params} ${
29 initrd ${defaults.initrd}
37 * Builds the default options.
39 buildMenuGrub2 = buildMenuAdditionalParamsGrub2 "";
42 if config.boot.loader.grub.forcei686 then
45 pkgs.stdenv.hostPlatform.efiArch;
48 * Given params to add to `params`, build a set of default options.
49 * Use this one when creating a variant (e.g. hidpi)
51 buildMenuAdditionalParamsGrub2 = additional:
54 name = "${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}";
55 params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}";
56 image = "/boot/${config.system.boot.loader.kernelFile}";
57 initrd = "/boot/initrd";
64 { class = "installer"; }
65 { class = "nomodeset"; params = "nomodeset"; }
66 { class = "copytoram"; params = "copytoram"; }
67 { class = "debug"; params = "debug"; }
71 # Timeout in syslinux is in units of 1/10 of a second.
72 # null means max timeout (35996, just under 1h in 1/10 seconds)
73 # 0 means disable timeout
74 syslinuxTimeout = if config.boot.loader.timeout == null then
77 config.boot.loader.timeout * 10;
79 # Timeout in grub is in seconds.
80 # null means max timeout (infinity)
81 # 0 means disable timeout
82 grubEfiTimeout = if config.boot.loader.timeout == null then
85 config.boot.loader.timeout;
87 # The configuration file for syslinux.
89 # Notes on syslinux configuration and UNetbootin compatibility:
90 # * Do not use '/syslinux/syslinux.cfg' as the path for this
91 # configuration. UNetbootin will not parse the file and use it as-is.
92 # This results in a broken configuration if the partition label does
93 # not match the specified config.isoImage.volumeID. For this reason
94 # we're using '/isolinux/isolinux.cfg'.
95 # * Use APPEND instead of adding command-line arguments directly after
97 # * COM32 entries (chainload, reboot, poweroff) are not recognized. They
98 # result in incorrect boot entries.
102 TIMEOUT ${builtins.toString syslinuxTimeout}
104 MENU BACKGROUND /isolinux/background.png
106 ${config.isoImage.syslinuxTheme}
111 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
112 LINUX /boot/${config.system.boot.loader.kernelFile}
113 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
114 INITRD /boot/${config.system.boot.loader.initrdFile}
116 # A variant to boot with 'nomodeset'
118 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset)
119 LINUX /boot/${config.system.boot.loader.kernelFile}
120 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
121 INITRD /boot/${config.system.boot.loader.initrdFile}
123 # A variant to boot with 'copytoram'
125 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram)
126 LINUX /boot/${config.system.boot.loader.kernelFile}
127 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
128 INITRD /boot/${config.system.boot.loader.initrdFile}
130 # A variant to boot with verbose logging to the console
132 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
133 LINUX /boot/${config.system.boot.loader.kernelFile}
134 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
135 INITRD /boot/${config.system.boot.loader.initrdFile}
137 # A variant to boot with a serial console enabled
139 MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8)
140 LINUX /boot/${config.system.boot.loader.kernelFile}
141 APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0,115200n8
142 INITRD /boot/${config.system.boot.loader.initrdFile}
145 isolinuxMemtest86Entry = ''
147 MENU LABEL Memtest86+
148 LINUX /boot/memtest.bin
149 APPEND ${toString config.boot.loader.grub.memtest86.params}
152 isolinuxCfg = lib.concatStringsSep "\n"
153 ([ baseIsolinuxCfg ] ++ lib.optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
155 refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null;
157 # Setup instructions for rEFInd.
159 if refindBinary != null then
161 # Adds rEFInd to the ISO.
162 cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/BOOT/
165 "# No refind for ${targetArch}"
168 grubPkgs = if config.boot.loader.grub.forcei686 then pkgs.pkgsi686Linux else pkgs;
175 # Search using a "marker file"
176 search --set=root --file /EFI/nixos-installer-image
181 set gfxmode=${lib.concatStringsSep "," [
182 # GRUB will use the first valid mode listed here.
183 # `auto` will sometimes choose the smallest valid mode it detects.
184 # So instead we'll list a lot of possibly valid modes :/
199 if [ "\$textmode" == "false" ]; then
200 terminal_output gfxterm
201 terminal_input console
203 terminal_output console
204 terminal_input console
205 # Sets colors for console term.
206 set menu_color_normal=cyan/blue
207 set menu_color_highlight=white/blue
210 ${ # When there is a theme configured, use it, otherwise use the background image.
211 if config.isoImage.grubTheme != null then ''
213 set theme=(\$root)/EFI/BOOT/grub-theme/theme.txt
215 $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n")
217 if background_image (\$root)/EFI/BOOT/efi-background.png; then
218 # Black background means transparent background when there
219 # is a background image set... This seems undocumented :(
220 set color_normal=black/black
221 set color_highlight=white/blue
223 # Falls back again to proper colors.
224 set menu_color_normal=cyan/blue
225 set menu_color_highlight=white/blue
230 # The EFI boot image.
232 # * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you
233 # will get white-on-black console-like text on sub-menus. *sigh*
234 efiDir = pkgs.runCommand "efi-directory" {
235 nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ];
238 mkdir -p $out/EFI/BOOT
240 # Add a marker so GRUB can find the filesystem.
241 touch $out/EFI/nixos-installer-image
243 # ALWAYS required modules.
245 # Basic modules for filesystems and partition schemes
260 # Allows rebooting into firmware setup interface
263 # EFI Graphics Output Protocol
276 # We're not using it anymore, but we'll leave it in so it can be used
277 # by user, with the console using "C"
280 # Graphical mode stuff
290 # File types for graphical mode
294 echo "Building GRUB with modules:"
295 for mod in ''${MODULES[@]}; do
299 # Modules that may or may not be available per-platform.
300 echo "Adding additional modules:"
301 for mod in efi_uga; do
302 if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then
308 # Make our own efi program, we can't rely on "grub-install" since it seems to
309 # probe for devices, even with --skip-fs-probe.
311 --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} \
312 -o $out/EFI/BOOT/BOOT${lib.toUpper targetArch}.EFI \
314 -O ${grubPkgs.grub2_efi.grubTarget} \
316 cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/BOOT/
318 cat <<EOF > $out/EFI/BOOT/grub.cfg
320 set textmode=${lib.boolToString (config.isoImage.forceTextMode)}
321 set timeout=${toString grubEfiTimeout}
324 # This message will only be viewable on the default (UEFI) console.
326 echo "Loading graphical boot menu..."
328 echo "Press 't' to use the text boot menu on this console..."
333 hiddenentry 'Text mode' --hotkey 't' {
334 loadfont (\$root)/EFI/BOOT/unicode.pf2
336 terminal_output console
339 ${lib.optionalString (config.isoImage.grubTheme != null) ''
340 hiddenentry 'GUI mode' --hotkey 'g' {
341 $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n")
343 terminal_output gfxterm
347 # If the parameter iso_path is set, append the findiso parameter to the kernel
348 # line. We need this to allow the nixos iso to be booted from grub directly.
349 if [ \''${iso_path} ] ; then
350 set isoboot="findiso=\''${iso_path}"
358 submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu {
360 submenu "Suggests resolution @720p" --class hidpi-720p {
362 ${buildMenuAdditionalParamsGrub2 "video=1280x720@60"}
364 submenu "Suggests resolution @1080p" --class hidpi-1080p {
366 ${buildMenuAdditionalParamsGrub2 "video=1920x1080@60"}
369 # If we boot into a graphical environment where X is autoran
370 # and always crashes, it makes the media unusable. Allow the user
372 submenu "Disable display-manager" --class quirk-disable-displaymanager {
374 ${buildMenuAdditionalParamsGrub2 "systemd.mask=display-manager.service"}
377 # Some laptop and convertibles have the panel installed in an
378 # inconvenient way, rotated away from the keyboard.
379 # Those entries makes it easier to use the installer.
381 submenu "Rotate framebuffer Clockwise" --class rotate-90cw {
383 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:1"}
385 submenu "Rotate framebuffer Upside-Down" --class rotate-180 {
387 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:2"}
389 submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw {
391 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:3"}
394 # As a proof of concept, mainly. (Not sure it has accessibility merits.)
396 submenu "Use black on white" --class accessibility-blakconwhite {
398 ${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"}
401 # Serial access is a must!
403 submenu "Serial console=ttyS0,115200n8" --class serial {
405 ${buildMenuAdditionalParamsGrub2 "console=ttyS0,115200n8"}
409 ${lib.optionalString (refindBinary != null) ''
410 # GRUB apparently cannot do "chainloader" operations on "CD".
411 if [ "\$root" != "cd0" ]; then
412 menuentry 'rEFInd' --class refind {
413 # Force root to be the FAT partition
414 # Otherwise it breaks rEFInd's boot
415 search --set=root --no-floppy --fs-uuid 1234-5678
416 chainloader (\$root)/EFI/BOOT/${refindBinary}
420 menuentry 'Firmware Setup' --class settings {
424 echo "If you see this message, your EFI system doesn't support this feature."
427 menuentry 'Shutdown' --class shutdown {
432 grub-script-check $out/EFI/BOOT/grub.cfg
437 efiImg = pkgs.runCommand "efi-image_eltorito" {
438 nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
441 # Be careful about determinism: du --apparent-size,
442 # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
444 mkdir ./contents && cd ./contents
446 cp -rp "${efiDir}"/EFI/BOOT/{grub.cfg,*.EFI,*.efi} ./EFI/BOOT
448 # Rewrite dates for everything in the FS
449 find . -exec touch --date=2000-01-01 {} +
451 # Round up to the nearest multiple of 1MB, for more deterministic du output
452 usage_size=$(( $(du -s --block-size=1M --apparent-size . | tr -cd '[:digit:]') * 1024 * 1024 ))
453 # Make the image 110% as big as the files need to make up for FAT overhead
454 image_size=$(( ($usage_size * 110) / 100 ))
455 # Make the image fit blocks of 1M
456 block_size=$((1024*1024))
457 image_size=$(( ($image_size / $block_size + 1) * $block_size ))
458 echo "Usage size: $usage_size"
459 echo "Image size: $image_size"
460 truncate --size=$image_size "$out"
461 mkfs.vfat --invariant -i 12345678 -n EFIBOOT "$out"
463 # Force a fixed order in mcopy for better determinism, and avoid file globbing
464 for d in $(find EFI -type d | sort); do
465 faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d"
468 for f in $(find EFI -type f | sort); do
469 mcopy -pvm -i "$out" "$f" "::/$f"
472 # Verify the FAT partition.
481 isoImage.isoName = lib.mkOption {
482 default = "${config.isoImage.isoBaseName}.iso";
483 type = lib.types.str;
485 Name of the generated ISO image file.
489 isoImage.isoBaseName = lib.mkOption {
490 default = config.system.nixos.distroId;
491 type = lib.types.str;
493 Prefix of the name of the generated ISO image file.
497 isoImage.compressImage = lib.mkOption {
499 type = lib.types.bool;
501 Whether the ISO image should be compressed using
506 isoImage.squashfsCompression = lib.mkOption {
507 default = "zstd -Xcompression-level 19";
508 type = lib.types.nullOr lib.types.str;
510 Compression settings to use for the squashfs nix store.
511 `null` disables compression.
513 example = "zstd -Xcompression-level 6";
516 isoImage.edition = lib.mkOption {
518 type = lib.types.str;
520 Specifies which edition string to use in the volume ID of the generated
525 isoImage.volumeID = lib.mkOption {
526 # nixos-$EDITION-$RELEASE-$ARCH
527 default = "nixos${lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
528 type = lib.types.str;
530 Specifies the label or volume ID of the generated ISO image.
531 Note that the label is used by stage 1 of the boot process to
532 mount the CD, so it should be reasonably distinctive.
536 isoImage.contents = lib.mkOption {
537 example = lib.literalExpression ''
538 [ { source = pkgs.memtest86 + "/memtest.bin";
539 target = "boot/memtest.bin";
544 This option lists files to be copied to fixed locations in the
549 isoImage.storeContents = lib.mkOption {
550 example = lib.literalExpression "[ pkgs.stdenv ]";
552 This option lists additional derivations to be included in the
553 Nix store in the generated ISO image.
557 isoImage.includeSystemBuildDependencies = lib.mkOption {
559 type = lib.types.bool;
561 Set this option to include all the needed sources etc in the
562 image. It significantly increases image size. Use that when
563 you want to be able to keep all the sources needed to build your
564 system or when you are going to install the system on a computer
565 with slow or non-existent network connection.
569 isoImage.makeBiosBootable = lib.mkOption {
570 # Before this option was introduced, images were BIOS-bootable if the
571 # hostPlatform was x86-based. This option is enabled by default for
572 # backwards compatibility.
574 # Also note that syslinux package currently cannot be cross-compiled from
575 # non-x86 platforms, so the default is false on non-x86 build platforms.
576 default = pkgs.stdenv.buildPlatform.isx86 && pkgs.stdenv.hostPlatform.isx86;
577 defaultText = lib.literalMD ''
578 `true` if both build and host platforms are x86-based architectures,
579 e.g. i686 and x86_64.
581 type = lib.types.bool;
583 Whether the ISO image should be a BIOS-bootable disk.
587 isoImage.makeEfiBootable = lib.mkOption {
589 type = lib.types.bool;
591 Whether the ISO image should be an EFI-bootable volume.
595 isoImage.makeUsbBootable = lib.mkOption {
597 type = lib.types.bool;
599 Whether the ISO image should be bootable from CD as well as USB.
603 isoImage.efiSplashImage = lib.mkOption {
604 default = pkgs.fetchurl {
605 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png";
606 sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x";
609 The splash image to use in the EFI bootloader.
613 isoImage.splashImage = lib.mkOption {
614 default = pkgs.fetchurl {
615 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png";
616 sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd";
619 The splash image to use in the legacy-boot bootloader.
623 isoImage.grubTheme = lib.mkOption {
624 default = pkgs.nixos-grub2-theme;
625 type = lib.types.nullOr (lib.types.either lib.types.path lib.types.package);
627 The grub2 theme used for UEFI boot.
631 isoImage.syslinuxTheme = lib.mkOption {
633 MENU TITLE ${config.system.nixos.distroName}
634 MENU RESOLUTION 800 600
641 MENU HELPMSGENDROW -1
644 # FG:AARRGGBB BG:AARRGGBB shadow
645 MENU COLOR BORDER 30;44 #00000000 #00000000 none
646 MENU COLOR SCREEN 37;40 #FF000000 #00E2E8FF none
647 MENU COLOR TABMSG 31;40 #80000000 #00000000 none
648 MENU COLOR TIMEOUT 1;37;40 #FF000000 #00000000 none
649 MENU COLOR TIMEOUT_MSG 37;40 #FF000000 #00000000 none
650 MENU COLOR CMDMARK 1;36;40 #FF000000 #00000000 none
651 MENU COLOR CMDLINE 37;40 #FF000000 #00000000 none
652 MENU COLOR TITLE 1;36;44 #00000000 #00000000 none
653 MENU COLOR UNSEL 37;44 #FF000000 #00000000 none
654 MENU COLOR SEL 7;37;40 #FFFFFFFF #FF5277C3 std
656 type = lib.types.str;
658 The syslinux theme used for BIOS boot.
662 isoImage.prependToMenuLabel = lib.mkOption {
664 type = lib.types.str;
665 example = "Install ";
667 The string to prepend before the menu label for the NixOS system.
668 This will be directly prepended (without whitespace) to the NixOS version
669 string, like for example if it is set to `XXX`:
671 `XXXNixOS 99.99-pre666`
675 isoImage.appendToMenuLabel = lib.mkOption {
676 default = " Installer";
677 type = lib.types.str;
678 example = " Live System";
680 The string to append after the menu label for the NixOS system.
681 This will be directly appended (without whitespace) to the NixOS version
682 string, like for example if it is set to `XXX`:
684 `NixOS 99.99-pre666XXX`
688 isoImage.forceTextMode = lib.mkOption {
690 type = lib.types.bool;
693 Whether to use text mode instead of graphical grub.
694 A value of `true` means graphical mode is not tried to be used.
696 This is useful for validating that graphics mode usage is not at the root cause of a problem with the iso image.
698 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.
704 # store them in lib so we can mkImageMediaOverride the
705 # entire file system layout in installation media (only)
706 config.lib.isoFileSystems = {
707 "/" = lib.mkImageMediaOverride
710 options = [ "mode=0755" ];
713 # Note that /dev/root is a symlink to the actual root device
714 # specified on the kernel command line, created in the stage 1
716 "/iso" = lib.mkImageMediaOverride
717 { device = "/dev/root";
718 neededForBoot = true;
722 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
723 # image) to make this a live CD.
724 "/nix/.ro-store" = lib.mkImageMediaOverride
725 { fsType = "squashfs";
726 device = "/iso/nix-store.squashfs";
727 options = [ "loop" ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi";
728 neededForBoot = true;
731 "/nix/.rw-store" = lib.mkImageMediaOverride
733 options = [ "mode=0755" ];
734 neededForBoot = true;
737 "/nix/store" = lib.mkImageMediaOverride
738 { fsType = "overlay";
741 "lowerdir=/nix/.ro-store"
742 "upperdir=/nix/.rw-store/store"
743 "workdir=/nix/.rw-store/work"
747 "/nix/.rw-store/store"
748 "/nix/.rw-store/work"
756 # Syslinux (and isolinux) only supports x86-based architectures.
757 assertion = config.isoImage.makeBiosBootable -> pkgs.stdenv.hostPlatform.isx86;
758 message = "BIOS boot is only supported on x86-based architectures.";
761 assertion = !(lib.stringLength config.isoImage.volumeID > 32);
762 # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
763 # Volume Identifier can only be 32 bytes
765 length = lib.stringLength config.isoImage.volumeID;
766 howmany = toString length;
767 toomany = toString (length - 32);
769 "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32.";
773 # Don't build the GRUB menu builder script, since we don't need it
774 # here and it causes a cyclic dependency.
775 boot.loader.grub.enable = false;
777 environment.systemPackages = [ grubPkgs.grub2 ]
778 ++ lib.optional (config.isoImage.makeBiosBootable) pkgs.syslinux
780 system.extraDependencies = [ grubPkgs.grub2_efi ];
782 # In stage 1 of the boot, mount the CD as the root FS by label so
783 # that we don't need to know its device. We pass the label of the
784 # root filesystem on the kernel command line, rather than in
785 # `fileSystems' below. This allows CD-to-USB converters such as
786 # UNetbootin to rewrite the kernel command line to pass the label or
787 # UUID of the USB stick. It would be nicer to write
788 # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't
791 [ "root=LABEL=${config.isoImage.volumeID}"
795 fileSystems = config.lib.isoFileSystems;
797 boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
799 boot.initrd.kernelModules = [ "loop" "overlay" ];
801 # Closures to be copied to the Nix store on the CD, namely the init
802 # script and the top-level system configuration directory.
803 isoImage.storeContents =
804 [ config.system.build.toplevel ] ++
805 lib.optional config.isoImage.includeSystemBuildDependencies
806 config.system.build.toplevel.drvPath;
808 # Individual files to be included on the CD, outside of the Nix
812 { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
813 target = "/boot/" + config.system.boot.loader.kernelFile;
815 { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
816 target = "/boot/" + config.system.boot.loader.initrdFile;
818 { source = pkgs.writeText "version" config.system.nixos.label;
819 target = "/version.txt";
821 ] ++ lib.optionals (config.isoImage.makeBiosBootable) [
822 { source = config.isoImage.splashImage;
823 target = "/isolinux/background.png";
825 { source = pkgs.substituteAll {
826 name = "isolinux.cfg";
827 src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
830 target = "/isolinux/isolinux.cfg";
832 { source = "${pkgs.syslinux}/share/syslinux";
833 target = "/isolinux";
835 ] ++ lib.optionals config.isoImage.makeEfiBootable [
837 target = "/boot/efi.img";
839 { source = "${efiDir}/EFI";
842 { source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub";
843 target = "/boot/grub";
845 { source = config.isoImage.efiSplashImage;
846 target = "/EFI/BOOT/efi-background.png";
848 ] ++ lib.optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [
849 { source = "${pkgs.memtest86plus}/memtest.bin";
850 target = "/boot/memtest.bin";
852 ] ++ lib.optionals (config.isoImage.grubTheme != null) [
853 { source = config.isoImage.grubTheme;
854 target = "/EFI/BOOT/grub-theme";
858 boot.loader.timeout = 10;
860 # Create the ISO image.
861 system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({
862 inherit (config.isoImage) isoName compressImage volumeID contents;
863 bootable = config.isoImage.makeBiosBootable;
864 bootImage = "/isolinux/isolinux.bin";
865 syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null;
866 squashfsContents = config.isoImage.storeContents;
867 squashfsCompression = config.isoImage.squashfsCompression;
868 } // lib.optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) {
870 isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
871 } // lib.optionalAttrs config.isoImage.makeEfiBootable {
873 efiBootImage = "boot/efi.img";
876 boot.postBootCommands =
878 # After booting, register the contents of the Nix store on the
879 # CD in the Nix database in the tmpfs.
880 ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration
882 # nixos-rebuild also requires a "system" profile and an
885 ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
888 # Add vfat support to the initrd to enable people to copy the
889 # contents of the CD to a bootable USB stick.
890 boot.initrd.supportedFilesystems = [ "vfat" ];