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
338 hiddenentry 'GUI mode' --hotkey 'g' {
339 $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/BOOT/grub-theme/%P\n")
341 terminal_output gfxterm
345 # If the parameter iso_path is set, append the findiso parameter to the kernel
346 # line. We need this to allow the nixos iso to be booted from grub directly.
347 if [ \''${iso_path} ] ; then
348 set isoboot="findiso=\''${iso_path}"
356 submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu {
358 submenu "Suggests resolution @720p" --class hidpi-720p {
360 ${buildMenuAdditionalParamsGrub2 "video=1280x720@60"}
362 submenu "Suggests resolution @1080p" --class hidpi-1080p {
364 ${buildMenuAdditionalParamsGrub2 "video=1920x1080@60"}
367 # If we boot into a graphical environment where X is autoran
368 # and always crashes, it makes the media unusable. Allow the user
370 submenu "Disable display-manager" --class quirk-disable-displaymanager {
372 ${buildMenuAdditionalParamsGrub2 "systemd.mask=display-manager.service"}
375 # Some laptop and convertibles have the panel installed in an
376 # inconvenient way, rotated away from the keyboard.
377 # Those entries makes it easier to use the installer.
379 submenu "Rotate framebuffer Clockwise" --class rotate-90cw {
381 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:1"}
383 submenu "Rotate framebuffer Upside-Down" --class rotate-180 {
385 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:2"}
387 submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw {
389 ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:3"}
392 # As a proof of concept, mainly. (Not sure it has accessibility merits.)
394 submenu "Use black on white" --class accessibility-blakconwhite {
396 ${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"}
399 # Serial access is a must!
401 submenu "Serial console=ttyS0,115200n8" --class serial {
403 ${buildMenuAdditionalParamsGrub2 "console=ttyS0,115200n8"}
407 ${lib.optionalString (refindBinary != null) ''
408 # GRUB apparently cannot do "chainloader" operations on "CD".
409 if [ "\$root" != "cd0" ]; then
410 menuentry 'rEFInd' --class refind {
411 # Force root to be the FAT partition
412 # Otherwise it breaks rEFInd's boot
413 search --set=root --no-floppy --fs-uuid 1234-5678
414 chainloader (\$root)/EFI/BOOT/${refindBinary}
418 menuentry 'Firmware Setup' --class settings {
422 echo "If you see this message, your EFI system doesn't support this feature."
425 menuentry 'Shutdown' --class shutdown {
430 grub-script-check $out/EFI/BOOT/grub.cfg
435 efiImg = pkgs.runCommand "efi-image_eltorito" {
436 nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
439 # Be careful about determinism: du --apparent-size,
440 # dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
442 mkdir ./contents && cd ./contents
444 cp -rp "${efiDir}"/EFI/BOOT/{grub.cfg,*.EFI,*.efi} ./EFI/BOOT
446 # Rewrite dates for everything in the FS
447 find . -exec touch --date=2000-01-01 {} +
449 # Round up to the nearest multiple of 1MB, for more deterministic du output
450 usage_size=$(( $(du -s --block-size=1M --apparent-size . | tr -cd '[:digit:]') * 1024 * 1024 ))
451 # Make the image 110% as big as the files need to make up for FAT overhead
452 image_size=$(( ($usage_size * 110) / 100 ))
453 # Make the image fit blocks of 1M
454 block_size=$((1024*1024))
455 image_size=$(( ($image_size / $block_size + 1) * $block_size ))
456 echo "Usage size: $usage_size"
457 echo "Image size: $image_size"
458 truncate --size=$image_size "$out"
459 mkfs.vfat --invariant -i 12345678 -n EFIBOOT "$out"
461 # Force a fixed order in mcopy for better determinism, and avoid file globbing
462 for d in $(find EFI -type d | sort); do
463 faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d"
466 for f in $(find EFI -type f | sort); do
467 mcopy -pvm -i "$out" "$f" "::/$f"
470 # Verify the FAT partition.
479 isoImage.isoName = lib.mkOption {
480 default = "${config.isoImage.isoBaseName}.iso";
481 type = lib.types.str;
483 Name of the generated ISO image file.
487 isoImage.isoBaseName = lib.mkOption {
488 default = config.system.nixos.distroId;
489 type = lib.types.str;
491 Prefix of the name of the generated ISO image file.
495 isoImage.compressImage = lib.mkOption {
497 type = lib.types.bool;
499 Whether the ISO image should be compressed using
504 isoImage.squashfsCompression = lib.mkOption {
505 default = "zstd -Xcompression-level 19";
506 type = lib.types.nullOr lib.types.str;
508 Compression settings to use for the squashfs nix store.
509 `null` disables compression.
511 example = "zstd -Xcompression-level 6";
514 isoImage.edition = lib.mkOption {
516 type = lib.types.str;
518 Specifies which edition string to use in the volume ID of the generated
523 isoImage.volumeID = lib.mkOption {
524 # nixos-$EDITION-$RELEASE-$ARCH
525 default = "nixos${lib.optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
526 type = lib.types.str;
528 Specifies the label or volume ID of the generated ISO image.
529 Note that the label is used by stage 1 of the boot process to
530 mount the CD, so it should be reasonably distinctive.
534 isoImage.contents = lib.mkOption {
535 example = lib.literalExpression ''
536 [ { source = pkgs.memtest86 + "/memtest.bin";
537 target = "boot/memtest.bin";
542 This option lists files to be copied to fixed locations in the
547 isoImage.storeContents = lib.mkOption {
548 example = lib.literalExpression "[ pkgs.stdenv ]";
550 This option lists additional derivations to be included in the
551 Nix store in the generated ISO image.
555 isoImage.includeSystemBuildDependencies = lib.mkOption {
557 type = lib.types.bool;
559 Set this option to include all the needed sources etc in the
560 image. It significantly increases image size. Use that when
561 you want to be able to keep all the sources needed to build your
562 system or when you are going to install the system on a computer
563 with slow or non-existent network connection.
567 isoImage.makeBiosBootable = lib.mkOption {
568 # Before this option was introduced, images were BIOS-bootable if the
569 # hostPlatform was x86-based. This option is enabled by default for
570 # backwards compatibility.
572 # Also note that syslinux package currently cannot be cross-compiled from
573 # non-x86 platforms, so the default is false on non-x86 build platforms.
574 default = pkgs.stdenv.buildPlatform.isx86 && pkgs.stdenv.hostPlatform.isx86;
575 defaultText = lib.literalMD ''
576 `true` if both build and host platforms are x86-based architectures,
577 e.g. i686 and x86_64.
579 type = lib.types.bool;
581 Whether the ISO image should be a BIOS-bootable disk.
585 isoImage.makeEfiBootable = lib.mkOption {
587 type = lib.types.bool;
589 Whether the ISO image should be an EFI-bootable volume.
593 isoImage.makeUsbBootable = lib.mkOption {
595 type = lib.types.bool;
597 Whether the ISO image should be bootable from CD as well as USB.
601 isoImage.efiSplashImage = lib.mkOption {
602 default = pkgs.fetchurl {
603 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png";
604 sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x";
607 The splash image to use in the EFI bootloader.
611 isoImage.splashImage = lib.mkOption {
612 default = pkgs.fetchurl {
613 url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png";
614 sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd";
617 The splash image to use in the legacy-boot bootloader.
621 isoImage.grubTheme = lib.mkOption {
622 default = pkgs.nixos-grub2-theme;
623 type = lib.types.nullOr (lib.types.either lib.types.path lib.types.package);
625 The grub2 theme used for UEFI boot.
629 isoImage.syslinuxTheme = lib.mkOption {
631 MENU TITLE ${config.system.nixos.distroName}
632 MENU RESOLUTION 800 600
639 MENU HELPMSGENDROW -1
642 # FG:AARRGGBB BG:AARRGGBB shadow
643 MENU COLOR BORDER 30;44 #00000000 #00000000 none
644 MENU COLOR SCREEN 37;40 #FF000000 #00E2E8FF none
645 MENU COLOR TABMSG 31;40 #80000000 #00000000 none
646 MENU COLOR TIMEOUT 1;37;40 #FF000000 #00000000 none
647 MENU COLOR TIMEOUT_MSG 37;40 #FF000000 #00000000 none
648 MENU COLOR CMDMARK 1;36;40 #FF000000 #00000000 none
649 MENU COLOR CMDLINE 37;40 #FF000000 #00000000 none
650 MENU COLOR TITLE 1;36;44 #00000000 #00000000 none
651 MENU COLOR UNSEL 37;44 #FF000000 #00000000 none
652 MENU COLOR SEL 7;37;40 #FFFFFFFF #FF5277C3 std
654 type = lib.types.str;
656 The syslinux theme used for BIOS boot.
660 isoImage.prependToMenuLabel = lib.mkOption {
662 type = lib.types.str;
663 example = "Install ";
665 The string to prepend before the menu label for the NixOS system.
666 This will be directly prepended (without whitespace) to the NixOS version
667 string, like for example if it is set to `XXX`:
669 `XXXNixOS 99.99-pre666`
673 isoImage.appendToMenuLabel = lib.mkOption {
674 default = " Installer";
675 type = lib.types.str;
676 example = " Live System";
678 The string to append after the menu label for the NixOS system.
679 This will be directly appended (without whitespace) to the NixOS version
680 string, like for example if it is set to `XXX`:
682 `NixOS 99.99-pre666XXX`
686 isoImage.forceTextMode = lib.mkOption {
688 type = lib.types.bool;
691 Whether to use text mode instead of graphical grub.
692 A value of `true` means graphical mode is not tried to be used.
694 This is useful for validating that graphics mode usage is not at the root cause of a problem with the iso image.
696 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.
702 # store them in lib so we can mkImageMediaOverride the
703 # entire file system layout in installation media (only)
704 config.lib.isoFileSystems = {
705 "/" = lib.mkImageMediaOverride
708 options = [ "mode=0755" ];
711 # Note that /dev/root is a symlink to the actual root device
712 # specified on the kernel command line, created in the stage 1
714 "/iso" = lib.mkImageMediaOverride
715 { device = "/dev/root";
716 neededForBoot = true;
720 # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
721 # image) to make this a live CD.
722 "/nix/.ro-store" = lib.mkImageMediaOverride
723 { fsType = "squashfs";
724 device = "/iso/nix-store.squashfs";
725 options = [ "loop" ] ++ lib.optional (config.boot.kernelPackages.kernel.kernelAtLeast "6.2") "threads=multi";
726 neededForBoot = true;
729 "/nix/.rw-store" = lib.mkImageMediaOverride
731 options = [ "mode=0755" ];
732 neededForBoot = true;
735 "/nix/store" = lib.mkImageMediaOverride
736 { fsType = "overlay";
739 "lowerdir=/nix/.ro-store"
740 "upperdir=/nix/.rw-store/store"
741 "workdir=/nix/.rw-store/work"
745 "/nix/.rw-store/store"
746 "/nix/.rw-store/work"
754 # Syslinux (and isolinux) only supports x86-based architectures.
755 assertion = config.isoImage.makeBiosBootable -> pkgs.stdenv.hostPlatform.isx86;
756 message = "BIOS boot is only supported on x86-based architectures.";
759 assertion = !(lib.stringLength config.isoImage.volumeID > 32);
760 # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
761 # Volume Identifier can only be 32 bytes
763 length = lib.stringLength config.isoImage.volumeID;
764 howmany = toString length;
765 toomany = toString (length - 32);
767 "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32.";
771 # Don't build the GRUB menu builder script, since we don't need it
772 # here and it causes a cyclic dependency.
773 boot.loader.grub.enable = false;
775 environment.systemPackages = [ grubPkgs.grub2 ]
776 ++ lib.optional (config.isoImage.makeBiosBootable) pkgs.syslinux
778 system.extraDependencies = [ grubPkgs.grub2_efi ];
780 # In stage 1 of the boot, mount the CD as the root FS by label so
781 # that we don't need to know its device. We pass the label of the
782 # root filesystem on the kernel command line, rather than in
783 # `fileSystems' below. This allows CD-to-USB converters such as
784 # UNetbootin to rewrite the kernel command line to pass the label or
785 # UUID of the USB stick. It would be nicer to write
786 # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't
789 [ "root=LABEL=${config.isoImage.volumeID}"
793 fileSystems = config.lib.isoFileSystems;
795 boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
797 boot.initrd.kernelModules = [ "loop" "overlay" ];
799 # Closures to be copied to the Nix store on the CD, namely the init
800 # script and the top-level system configuration directory.
801 isoImage.storeContents =
802 [ config.system.build.toplevel ] ++
803 lib.optional config.isoImage.includeSystemBuildDependencies
804 config.system.build.toplevel.drvPath;
806 # Individual files to be included on the CD, outside of the Nix
810 { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
811 target = "/boot/" + config.system.boot.loader.kernelFile;
813 { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
814 target = "/boot/" + config.system.boot.loader.initrdFile;
816 { source = pkgs.writeText "version" config.system.nixos.label;
817 target = "/version.txt";
819 ] ++ lib.optionals (config.isoImage.makeBiosBootable) [
820 { source = config.isoImage.splashImage;
821 target = "/isolinux/background.png";
823 { source = pkgs.substituteAll {
824 name = "isolinux.cfg";
825 src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
828 target = "/isolinux/isolinux.cfg";
830 { source = "${pkgs.syslinux}/share/syslinux";
831 target = "/isolinux";
833 ] ++ lib.optionals config.isoImage.makeEfiBootable [
835 target = "/boot/efi.img";
837 { source = "${efiDir}/EFI";
840 { source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/BOOT/grub.cfg") + "/grub";
841 target = "/boot/grub";
843 { source = config.isoImage.efiSplashImage;
844 target = "/EFI/BOOT/efi-background.png";
846 ] ++ lib.optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [
847 { source = "${pkgs.memtest86plus}/memtest.bin";
848 target = "/boot/memtest.bin";
850 ] ++ lib.optionals (config.isoImage.grubTheme != null) [
851 { source = config.isoImage.grubTheme;
852 target = "/EFI/BOOT/grub-theme";
856 boot.loader.timeout = 10;
858 # Create the ISO image.
859 system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({
860 inherit (config.isoImage) isoName compressImage volumeID contents;
861 bootable = config.isoImage.makeBiosBootable;
862 bootImage = "/isolinux/isolinux.bin";
863 syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null;
864 squashfsContents = config.isoImage.storeContents;
865 squashfsCompression = config.isoImage.squashfsCompression;
866 } // lib.optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) {
868 isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
869 } // lib.optionalAttrs config.isoImage.makeEfiBootable {
871 efiBootImage = "boot/efi.img";
874 boot.postBootCommands =
876 # After booting, register the contents of the Nix store on the
877 # CD in the Nix database in the tmpfs.
878 ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration
880 # nixos-rebuild also requires a "system" profile and an
883 ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
886 # Add vfat support to the initrd to enable people to copy the
887 # contents of the CD to a bootable USB stick.
888 boot.initrd.supportedFilesystems = [ "vfat" ];