summary refs log tree commit diff
path: root/nixos/modules/installer/cd-dvd
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/installer/cd-dvd')
-rw-r--r--nixos/modules/installer/cd-dvd/channel.nix49
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix50
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix56
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix38
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5-new-kernel.nix7
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix50
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix7
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix811
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-aarch64.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/sd-image.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix160
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt89
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc.nix163
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix172
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball.nix93
19 files changed, 1829 insertions, 0 deletions
diff --git a/nixos/modules/installer/cd-dvd/channel.nix b/nixos/modules/installer/cd-dvd/channel.nix
new file mode 100644
index 00000000000..92164d65e53
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/channel.nix
@@ -0,0 +1,49 @@
+# Provide an initial copy of the NixOS channel so that the user
+# doesn't need to run "nix-channel --update" first.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  nixpkgs = lib.cleanSource pkgs.path;
+
+  # We need a copy of the Nix expressions for Nixpkgs and NixOS on the
+  # CD.  These are installed into the "nixos" channel of the root
+  # user, as expected by nixos-rebuild/nixos-install. FIXME: merge
+  # with make-channel.nix.
+  channelSources = pkgs.runCommand "nixos-${config.system.nixos.version}"
+    { preferLocalBuild = true; }
+    ''
+      mkdir -p $out
+      cp -prd ${nixpkgs.outPath} $out/nixos
+      chmod -R u+w $out/nixos
+      if [ ! -e $out/nixos/nixpkgs ]; then
+        ln -s . $out/nixos/nixpkgs
+      fi
+      ${optionalString (config.system.nixos.revision != null) ''
+        echo -n ${config.system.nixos.revision} > $out/nixos/.git-revision
+      ''}
+      echo -n ${config.system.nixos.versionSuffix} > $out/nixos/.version-suffix
+      echo ${config.system.nixos.versionSuffix} | sed -e s/pre// > $out/nixos/svn-revision
+    '';
+
+in
+
+{
+  # Provide the NixOS/Nixpkgs sources in /etc/nixos.  This is required
+  # for nixos-install.
+  boot.postBootCommands = mkAfter
+    ''
+      if ! [ -e /var/lib/nixos/did-channel-init ]; then
+        echo "unpacking the NixOS/Nixpkgs sources..."
+        mkdir -p /nix/var/nix/profiles/per-user/root
+        ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/per-user/root/channels \
+          -i ${channelSources} --quiet --option build-use-substitutes false
+        mkdir -m 0700 -p /root/.nix-defexpr
+        ln -s /nix/var/nix/profiles/per-user/root/channels /root/.nix-defexpr/channels
+        mkdir -m 0755 -p /var/lib/nixos
+        touch /var/lib/nixos/did-channel-init
+      fi
+    '';
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
new file mode 100644
index 00000000000..618057618d0
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -0,0 +1,50 @@
+# This module contains the basic configuration for building a NixOS
+# installation CD.
+
+{ config, lib, options, pkgs, ... }:
+
+with lib;
+
+{
+  imports =
+    [ ./iso-image.nix
+
+      # Profiles of this basic installation CD.
+      ../../profiles/all-hardware.nix
+      ../../profiles/base.nix
+      ../../profiles/installation-device.nix
+    ];
+
+  # Adds terminus_font for people with HiDPI displays
+  console.packages = options.console.packages.default ++ [ pkgs.terminus_font ];
+
+  # ISO naming.
+  isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixos.label}-${pkgs.stdenv.hostPlatform.system}.iso";
+
+  # EFI booting
+  isoImage.makeEfiBootable = true;
+
+  # USB booting
+  isoImage.makeUsbBootable = true;
+
+  # Add Memtest86+ to the CD.
+  boot.loader.grub.memtest86.enable = true;
+
+  # An installation media cannot tolerate a host config defined file
+  # system layout on a fresh machine, before it has been formatted.
+  swapDevices = mkImageMediaOverride [ ];
+  fileSystems = mkImageMediaOverride config.lib.isoFileSystems;
+
+  boot.postBootCommands = ''
+    for o in $(</proc/cmdline); do
+      case "$o" in
+        live.nixos.passwd=*)
+          set -- $(IFS==; echo $o)
+          echo "nixos:$2" | ${pkgs.shadow}/bin/chpasswd
+          ;;
+      esac
+    done
+  '';
+
+  system.stateVersion = mkDefault "18.03";
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
new file mode 100644
index 00000000000..fa19daf1328
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-base.nix
@@ -0,0 +1,56 @@
+# This module contains the basic configuration for building a graphical NixOS
+# installation CD.
+
+{ lib, pkgs, ... }:
+
+with lib;
+
+{
+  imports = [ ./installation-cd-base.nix ];
+
+  # Whitelist wheel users to do anything
+  # This is useful for things like pkexec
+  #
+  # WARNING: this is dangerous for systems
+  # outside the installation-cd and shouldn't
+  # be used anywhere else.
+  security.polkit.extraConfig = ''
+    polkit.addRule(function(action, subject) {
+      if (subject.isInGroup("wheel")) {
+        return polkit.Result.YES;
+      }
+    });
+  '';
+
+  services.xserver.enable = true;
+
+  # Provide networkmanager for easy wireless configuration.
+  networking.networkmanager.enable = true;
+  networking.wireless.enable = mkForce false;
+
+  # KDE complains if power management is disabled (to be precise, if
+  # there is no power management backend such as upower).
+  powerManagement.enable = true;
+
+  # Enable sound in graphical iso's.
+  hardware.pulseaudio.enable = true;
+
+  environment.systemPackages = [
+    # Include gparted for partitioning disks.
+    pkgs.gparted
+
+    # Include some editors.
+    pkgs.vim
+    pkgs.bvi # binary editor
+    pkgs.joe
+
+    # Include some version control tools.
+    pkgs.git
+
+    # Firefox for reading the manual.
+    pkgs.firefox
+
+    pkgs.glxinfo
+  ];
+
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
new file mode 100644
index 00000000000..303493741f3
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-gnome.nix
@@ -0,0 +1,38 @@
+# This module defines a NixOS installation CD that contains GNOME.
+
+{ lib, ... }:
+
+with lib;
+
+{
+  imports = [ ./installation-cd-graphical-base.nix ];
+
+  isoImage.edition = "gnome";
+
+  services.xserver.desktopManager.gnome = {
+    # Add Firefox and other tools useful for installation to the launcher
+    favoriteAppsOverride = ''
+      [org.gnome.shell]
+      favorite-apps=[ 'firefox.desktop', 'nixos-manual.desktop', 'org.gnome.Terminal.desktop', 'org.gnome.Nautilus.desktop', 'gparted.desktop' ]
+    '';
+    enable = true;
+  };
+
+  services.xserver.displayManager = {
+    gdm = {
+      enable = true;
+      # autoSuspend makes the machine automatically suspend after inactivity.
+      # It's possible someone could/try to ssh'd into the machine and obviously
+      # have issues because it's inactive.
+      # See:
+      # * https://github.com/NixOS/nixpkgs/pull/63790
+      # * https://gitlab.gnome.org/GNOME/gnome-control-center/issues/22
+      autoSuspend = false;
+    };
+    autoLogin = {
+      enable = true;
+      user = "nixos";
+    };
+  };
+
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5-new-kernel.nix
new file mode 100644
index 00000000000..d98325a99ac
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5-new-kernel.nix
@@ -0,0 +1,7 @@
+{ pkgs, ... }:
+
+{
+  imports = [ ./installation-cd-graphical-plasma5.nix ];
+
+  boot.kernelPackages = pkgs.linuxPackages_latest;
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
new file mode 100644
index 00000000000..098c2b2870b
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical-plasma5.nix
@@ -0,0 +1,50 @@
+# This module defines a NixOS installation CD that contains X11 and
+# Plasma 5.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+  imports = [ ./installation-cd-graphical-base.nix ];
+
+  isoImage.edition = "plasma5";
+
+  services.xserver = {
+    desktopManager.plasma5 = {
+      enable = true;
+    };
+
+    # Automatically login as nixos.
+    displayManager = {
+      sddm.enable = true;
+      autoLogin = {
+        enable = true;
+        user = "nixos";
+      };
+    };
+  };
+
+  environment.systemPackages = with pkgs; [
+    # Graphical text editor
+    kate
+  ];
+
+  system.activationScripts.installerDesktop = let
+
+    # Comes from documentation.nix when xserver and nixos.enable are true.
+    manualDesktopFile = "/run/current-system/sw/share/applications/nixos-manual.desktop";
+
+    homeDir = "/home/nixos/";
+    desktopDir = homeDir + "Desktop/";
+
+  in ''
+    mkdir -p ${desktopDir}
+    chown nixos ${homeDir} ${desktopDir}
+
+    ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
+    ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
+    ln -sfT ${pkgs.konsole}/share/applications/org.kde.konsole.desktop ${desktopDir + "org.kde.konsole.desktop"}
+  '';
+
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
new file mode 100644
index 00000000000..3911a2b01b1
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
@@ -0,0 +1,7 @@
+{ pkgs, ... }:
+
+{
+  imports = [ ./installation-cd-minimal.nix ];
+
+  boot.kernelPackages = pkgs.linuxPackages_latest;
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
new file mode 100644
index 00000000000..97506045e0e
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
@@ -0,0 +1,14 @@
+# This module defines a small NixOS installation CD.  It does not
+# contain any graphical stuff.
+
+{ ... }:
+
+{
+  imports =
+    [ ./installation-cd-base.nix
+    ];
+
+  isoImage.edition = "minimal";
+
+  fonts.fontconfig.enable = false;
+}
diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix
new file mode 100644
index 00000000000..3ff1b3d670e
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -0,0 +1,811 @@
+# This module creates a bootable ISO image containing the given NixOS
+# configuration.  The derivation for the ISO image will be placed in
+# config.system.build.isoImage.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+  /**
+   * Given a list of `options`, concats the result of mapping each options
+   * to a menuentry for use in grub.
+   *
+   *  * defaults: {name, image, params, initrd}
+   *  * options: [ option... ]
+   *  * option: {name, params, class}
+   */
+  menuBuilderGrub2 =
+  defaults: options: lib.concatStrings
+    (
+      map
+      (option: ''
+        menuentry '${defaults.name} ${
+        # Name appended to menuentry defaults to params if no specific name given.
+        option.name or (if option ? params then "(${option.params})" else "")
+        }' ${if option ? class then " --class ${option.class}" else ""} {
+          linux ${defaults.image} \''${isoboot} ${defaults.params} ${
+            option.params or ""
+          }
+          initrd ${defaults.initrd}
+        }
+      '')
+      options
+    )
+  ;
+
+  /**
+   * Given a `config`, builds the default options.
+   */
+  buildMenuGrub2 = config:
+    buildMenuAdditionalParamsGrub2 config ""
+  ;
+
+  /**
+   * Given a `config` and params to add to `params`, build a set of default options.
+   * Use this one when creating a variant (e.g. hidpi)
+   */
+  buildMenuAdditionalParamsGrub2 = config: additional:
+  let
+    finalCfg = {
+      name = "NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}";
+      params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}";
+      image = "/boot/${config.system.boot.loader.kernelFile}";
+      initrd = "/boot/initrd";
+    };
+  in
+    menuBuilderGrub2
+    finalCfg
+    [
+      { class = "installer"; }
+      { class = "nomodeset"; params = "nomodeset"; }
+      { class = "copytoram"; params = "copytoram"; }
+      { class = "debug";     params = "debug"; }
+    ]
+  ;
+
+  # Timeout in syslinux is in units of 1/10 of a second.
+  # 0 is used to disable timeouts.
+  syslinuxTimeout = if config.boot.loader.timeout == null then
+      0
+    else
+      max (config.boot.loader.timeout * 10) 1;
+
+
+  max = x: y: if x > y then x else y;
+
+  # The configuration file for syslinux.
+
+  # Notes on syslinux configuration and UNetbootin compatiblity:
+  #   * Do not use '/syslinux/syslinux.cfg' as the path for this
+  #     configuration. UNetbootin will not parse the file and use it as-is.
+  #     This results in a broken configuration if the partition label does
+  #     not match the specified config.isoImage.volumeID. For this reason
+  #     we're using '/isolinux/isolinux.cfg'.
+  #   * Use APPEND instead of adding command-line arguments directly after
+  #     the LINUX entries.
+  #   * COM32 entries (chainload, reboot, poweroff) are not recognized. They
+  #     result in incorrect boot entries.
+
+  baseIsolinuxCfg = ''
+    SERIAL 0 115200
+    TIMEOUT ${builtins.toString syslinuxTimeout}
+    UI vesamenu.c32
+    MENU TITLE NixOS
+    MENU BACKGROUND /isolinux/background.png
+    MENU RESOLUTION 800 600
+    MENU CLEAR
+    MENU ROWS 6
+    MENU CMDLINEROW -4
+    MENU TIMEOUTROW -3
+    MENU TABMSGROW  -2
+    MENU HELPMSGROW -1
+    MENU HELPMSGENDROW -1
+    MENU MARGIN 0
+
+    #                                FG:AARRGGBB  BG:AARRGGBB   shadow
+    MENU COLOR BORDER       30;44      #00000000    #00000000   none
+    MENU COLOR SCREEN       37;40      #FF000000    #00E2E8FF   none
+    MENU COLOR TABMSG       31;40      #80000000    #00000000   none
+    MENU COLOR TIMEOUT      1;37;40    #FF000000    #00000000   none
+    MENU COLOR TIMEOUT_MSG  37;40      #FF000000    #00000000   none
+    MENU COLOR CMDMARK      1;36;40    #FF000000    #00000000   none
+    MENU COLOR CMDLINE      37;40      #FF000000    #00000000   none
+    MENU COLOR TITLE        1;36;44    #00000000    #00000000   none
+    MENU COLOR UNSEL        37;44      #FF000000    #00000000   none
+    MENU COLOR SEL          7;37;40    #FFFFFFFF    #FF5277C3   std
+
+    DEFAULT boot
+
+    LABEL boot
+    MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}
+    LINUX /boot/${config.system.boot.loader.kernelFile}
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+    INITRD /boot/${config.system.boot.loader.initrdFile}
+
+    # A variant to boot with 'nomodeset'
+    LABEL boot-nomodeset
+    MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset)
+    LINUX /boot/${config.system.boot.loader.kernelFile}
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset
+    INITRD /boot/${config.system.boot.loader.initrdFile}
+
+    # A variant to boot with 'copytoram'
+    LABEL boot-copytoram
+    MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram)
+    LINUX /boot/${config.system.boot.loader.kernelFile}
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram
+    INITRD /boot/${config.system.boot.loader.initrdFile}
+
+    # A variant to boot with verbose logging to the console
+    LABEL boot-debug
+    MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug)
+    LINUX /boot/${config.system.boot.loader.kernelFile}
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7
+    INITRD /boot/${config.system.boot.loader.initrdFile}
+
+    # A variant to boot with a serial console enabled
+    LABEL boot-serial
+    MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8)
+    LINUX /boot/${config.system.boot.loader.kernelFile}
+    APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0,115200n8
+    INITRD /boot/${config.system.boot.loader.initrdFile}
+  '';
+
+  isolinuxMemtest86Entry = ''
+    LABEL memtest
+    MENU LABEL Memtest86+
+    LINUX /boot/memtest.bin
+    APPEND ${toString config.boot.loader.grub.memtest86.params}
+  '';
+
+  isolinuxCfg = concatStringsSep "\n"
+    ([ baseIsolinuxCfg ] ++ optional config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
+
+  refindBinary = if targetArch == "x64" || targetArch == "aa64" then "refind_${targetArch}.efi" else null;
+
+  # Setup instructions for rEFInd.
+  refind =
+    if refindBinary != null then
+      ''
+      # Adds rEFInd to the ISO.
+      cp -v ${pkgs.refind}/share/refind/${refindBinary} $out/EFI/boot/
+      ''
+    else
+      "# No refind for ${targetArch}"
+  ;
+
+  grubPkgs = if config.boot.loader.grub.forcei686 then pkgs.pkgsi686Linux else pkgs;
+
+  grubMenuCfg = ''
+    #
+    # Menu configuration
+    #
+
+    # Search using a "marker file"
+    search --set=root --file /EFI/nixos-installer-image
+
+    insmod gfxterm
+    insmod png
+    set gfxpayload=keep
+    set gfxmode=${concatStringsSep "," [
+      # GRUB will use the first valid mode listed here.
+      # `auto` will sometimes choose the smallest valid mode it detects.
+      # So instead we'll list a lot of possibly valid modes :/
+      #"3840x2160"
+      #"2560x1440"
+      "1920x1080"
+      "1366x768"
+      "1280x720"
+      "1024x768"
+      "800x600"
+      "auto"
+    ]}
+
+    # Fonts can be loaded?
+    # (This font is assumed to always be provided as a fallback by NixOS)
+    if loadfont (\$root)/EFI/boot/unicode.pf2; then
+      set with_fonts=true
+    fi
+    if [ "\$textmode" != "true" -a "\$with_fonts" == "true" ]; then
+      # Use graphical term, it can be either with background image or a theme.
+      # input is "console", while output is "gfxterm".
+      # This enables "serial" input and output only when possible.
+      # Otherwise the failure mode is to not even enable gfxterm.
+      if test "\$with_serial" == "yes"; then
+        terminal_output gfxterm serial
+        terminal_input  console serial
+      else
+        terminal_output gfxterm
+        terminal_input  console
+      fi
+    else
+      # Sets colors for the non-graphical term.
+      set menu_color_normal=cyan/blue
+      set menu_color_highlight=white/blue
+    fi
+
+    ${ # When there is a theme configured, use it, otherwise use the background image.
+    if config.isoImage.grubTheme != null then ''
+      # Sets theme.
+      set theme=(\$root)/EFI/boot/grub-theme/theme.txt
+      # Load theme fonts
+      $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
+    '' else ''
+      if background_image (\$root)/EFI/boot/efi-background.png; then
+        # Black background means transparent background when there
+        # is a background image set... This seems undocumented :(
+        set color_normal=black/black
+        set color_highlight=white/blue
+      else
+        # Falls back again to proper colors.
+        set menu_color_normal=cyan/blue
+        set menu_color_highlight=white/blue
+      fi
+    ''}
+  '';
+
+  # The EFI boot image.
+  # Notes about grub:
+  #  * Yes, the grubMenuCfg has to be repeated in all submenus. Otherwise you
+  #    will get white-on-black console-like text on sub-menus. *sigh*
+  efiDir = pkgs.runCommand "efi-directory" {
+    nativeBuildInputs = [ pkgs.buildPackages.grub2_efi ];
+    strictDeps = true;
+  } ''
+    mkdir -p $out/EFI/boot/
+
+    # Add a marker so GRUB can find the filesystem.
+    touch $out/EFI/nixos-installer-image
+
+    # ALWAYS required modules.
+    MODULES="fat iso9660 part_gpt part_msdos \
+             normal boot linux configfile loopback chain halt \
+             efifwsetup efi_gop \
+             ls search search_label search_fs_uuid search_fs_file \
+             gfxmenu gfxterm gfxterm_background gfxterm_menu test all_video loadenv \
+             exfat ext2 ntfs btrfs hfsplus udf \
+             videoinfo png \
+             echo serial \
+            "
+
+    echo "Building GRUB with modules:"
+    for mod in $MODULES; do
+      echo " - $mod"
+    done
+
+    # Modules that may or may not be available per-platform.
+    echo "Adding additional modules:"
+    for mod in efi_uga; do
+      if [ -f ${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget}/$mod.mod ]; then
+        echo " - $mod"
+        MODULES+=" $mod"
+      fi
+    done
+
+    # Make our own efi program, we can't rely on "grub-install" since it seems to
+    # probe for devices, even with --skip-fs-probe.
+    grub-mkimage --directory=${grubPkgs.grub2_efi}/lib/grub/${grubPkgs.grub2_efi.grubTarget} -o $out/EFI/boot/boot${targetArch}.efi -p /EFI/boot -O ${grubPkgs.grub2_efi.grubTarget} \
+      $MODULES
+    cp ${grubPkgs.grub2_efi}/share/grub/unicode.pf2 $out/EFI/boot/
+
+    cat <<EOF > $out/EFI/boot/grub.cfg
+
+    set with_fonts=false
+    set textmode=false
+    # If you want to use serial for "terminal_*" commands, you need to set one up:
+    #   Example manual configuration:
+    #    → serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1
+    # This uses the defaults, and makes the serial terminal available.
+    set with_serial=no
+    if serial; then set with_serial=yes ;fi
+    export with_serial
+    clear
+    set timeout=10
+
+    # This message will only be viewable when "gfxterm" is not used.
+    echo ""
+    echo "Loading graphical boot menu..."
+    echo ""
+    echo "Press 't' to use the text boot menu on this console..."
+    echo ""
+
+    ${grubMenuCfg}
+
+    hiddenentry 'Text mode' --hotkey 't' {
+      loadfont (\$root)/EFI/boot/unicode.pf2
+      set textmode=true
+      terminal_output gfxterm console
+    }
+    hiddenentry 'GUI mode' --hotkey 'g' {
+      $(find ${config.isoImage.grubTheme} -iname '*.pf2' -printf "loadfont (\$root)/EFI/boot/grub-theme/%P\n")
+      set textmode=false
+      terminal_output gfxterm
+    }
+
+
+    # If the parameter iso_path is set, append the findiso parameter to the kernel
+    # line. We need this to allow the nixos iso to be booted from grub directly.
+    if [ \''${iso_path} ] ; then
+      set isoboot="findiso=\''${iso_path}"
+    fi
+
+    #
+    # Menu entries
+    #
+
+    ${buildMenuGrub2 config}
+    submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu {
+      ${grubMenuCfg}
+      submenu "Suggests resolution @720p" --class hidpi-720p {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "video=1280x720@60"}
+      }
+      submenu "Suggests resolution @1080p" --class hidpi-1080p {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "video=1920x1080@60"}
+      }
+
+      # If we boot into a graphical environment where X is autoran
+      # and always crashes, it makes the media unusable. Allow the user
+      # to disable this.
+      submenu "Disable display-manager" --class quirk-disable-displaymanager {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "systemd.mask=display-manager.service"}
+      }
+
+      # Some laptop and convertibles have the panel installed in an
+      # inconvenient way, rotated away from the keyboard.
+      # Those entries makes it easier to use the installer.
+      submenu "" {return}
+      submenu "Rotate framebuffer Clockwise" --class rotate-90cw {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:1"}
+      }
+      submenu "Rotate framebuffer Upside-Down" --class rotate-180 {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:2"}
+      }
+      submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:3"}
+      }
+
+      # As a proof of concept, mainly. (Not sure it has accessibility merits.)
+      submenu "" {return}
+      submenu "Use black on white" --class accessibility-blakconwhite {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "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"}
+      }
+
+      # Serial access is a must!
+      submenu "" {return}
+      submenu "Serial console=ttyS0,115200n8" --class serial {
+        ${grubMenuCfg}
+        ${buildMenuAdditionalParamsGrub2 config "console=ttyS0,115200n8"}
+      }
+    }
+
+    ${lib.optionalString (refindBinary != null) ''
+    # GRUB apparently cannot do "chainloader" operations on "CD".
+    if [ "\$root" != "cd0" ]; then
+      # Force root to be the FAT partition
+      # Otherwise it breaks rEFInd's boot
+      search --set=root --no-floppy --fs-uuid 1234-5678
+      menuentry 'rEFInd' --class refind {
+        chainloader (\$root)/EFI/boot/${refindBinary}
+      }
+    fi
+    ''}
+    menuentry 'Firmware Setup' --class settings {
+      fwsetup
+      clear
+      echo ""
+      echo "If you see this message, your EFI system doesn't support this feature."
+      echo ""
+    }
+    menuentry 'Shutdown' --class shutdown {
+      halt
+    }
+    EOF
+
+    ${refind}
+  '';
+
+  efiImg = pkgs.runCommand "efi-image_eltorito" {
+    nativeBuildInputs = [ pkgs.buildPackages.mtools pkgs.buildPackages.libfaketime pkgs.buildPackages.dosfstools ];
+    strictDeps = true;
+  }
+    # Be careful about determinism: du --apparent-size,
+    #   dates (cp -p, touch, mcopy -m, faketime for label), IDs (mkfs.vfat -i)
+    ''
+      mkdir ./contents && cd ./contents
+      cp -rp "${efiDir}"/EFI .
+      mkdir ./boot
+      cp -p "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}" \
+        "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}" ./boot/
+
+      # Rewrite dates for everything in the FS
+      find . -exec touch --date=2000-01-01 {} +
+
+      # Round up to the nearest multiple of 1MB, for more deterministic du output
+      usage_size=$(( $(du -s --block-size=1M --apparent-size . | tr -cd '[:digit:]') * 1024 * 1024 ))
+      # Make the image 110% as big as the files need to make up for FAT overhead
+      image_size=$(( ($usage_size * 110) / 100 ))
+      # Make the image fit blocks of 1M
+      block_size=$((1024*1024))
+      image_size=$(( ($image_size / $block_size + 1) * $block_size ))
+      echo "Usage size: $usage_size"
+      echo "Image size: $image_size"
+      truncate --size=$image_size "$out"
+      faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out"
+
+      # Force a fixed order in mcopy for better determinism, and avoid file globbing
+      for d in $(find EFI boot -type d | sort); do
+        faketime "2000-01-01 00:00:00" mmd -i "$out" "::/$d"
+      done
+
+      for f in $(find EFI boot -type f | sort); do
+        mcopy -pvm -i "$out" "$f" "::/$f"
+      done
+
+      # Verify the FAT partition.
+      fsck.vfat -vn "$out"
+    ''; # */
+
+  # Name used by UEFI for architectures.
+  targetArch =
+    if pkgs.stdenv.isi686 || config.boot.loader.grub.forcei686 then
+      "ia32"
+    else if pkgs.stdenv.isx86_64 then
+      "x64"
+    else if pkgs.stdenv.isAarch32 then
+      "arm"
+    else if pkgs.stdenv.isAarch64 then
+      "aa64"
+    else
+      throw "Unsupported architecture";
+
+  # Syslinux (and isolinux) only supports x86-based architectures.
+  canx86BiosBoot = pkgs.stdenv.hostPlatform.isx86;
+
+in
+
+{
+  options = {
+
+    isoImage.isoName = mkOption {
+      default = "${config.isoImage.isoBaseName}.iso";
+      description = ''
+        Name of the generated ISO image file.
+      '';
+    };
+
+    isoImage.isoBaseName = mkOption {
+      default = "nixos";
+      description = ''
+        Prefix of the name of the generated ISO image file.
+      '';
+    };
+
+    isoImage.compressImage = mkOption {
+      default = false;
+      description = ''
+        Whether the ISO image should be compressed using
+        <command>zstd</command>.
+      '';
+    };
+
+    isoImage.squashfsCompression = mkOption {
+      default = with pkgs.stdenv.targetPlatform; "xz -Xdict-size 100% "
+                + lib.optionalString (isx86_32 || isx86_64) "-Xbcj x86"
+                # Untested but should also reduce size for these platforms
+                + lib.optionalString (isAarch32 || isAarch64) "-Xbcj arm"
+                + lib.optionalString (isPowerPC) "-Xbcj powerpc"
+                + lib.optionalString (isSparc) "-Xbcj sparc";
+      description = ''
+        Compression settings to use for the squashfs nix store.
+      '';
+      example = "zstd -Xcompression-level 6";
+    };
+
+    isoImage.edition = mkOption {
+      default = "";
+      description = ''
+        Specifies which edition string to use in the volume ID of the generated
+        ISO image.
+      '';
+    };
+
+    isoImage.volumeID = mkOption {
+      # nixos-$EDITION-$RELEASE-$ARCH
+      default = "nixos${optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
+      description = ''
+        Specifies the label or volume ID of the generated ISO image.
+        Note that the label is used by stage 1 of the boot process to
+        mount the CD, so it should be reasonably distinctive.
+      '';
+    };
+
+    isoImage.contents = mkOption {
+      example = literalExpression ''
+        [ { source = pkgs.memtest86 + "/memtest.bin";
+            target = "boot/memtest.bin";
+          }
+        ]
+      '';
+      description = ''
+        This option lists files to be copied to fixed locations in the
+        generated ISO image.
+      '';
+    };
+
+    isoImage.storeContents = mkOption {
+      example = literalExpression "[ pkgs.stdenv ]";
+      description = ''
+        This option lists additional derivations to be included in the
+        Nix store in the generated ISO image.
+      '';
+    };
+
+    isoImage.includeSystemBuildDependencies = mkOption {
+      default = false;
+      description = ''
+        Set this option to include all the needed sources etc in the
+        image. It significantly increases image size. Use that when
+        you want to be able to keep all the sources needed to build your
+        system or when you are going to install the system on a computer
+        with slow or non-existent network connection.
+      '';
+    };
+
+    isoImage.makeEfiBootable = mkOption {
+      default = false;
+      description = ''
+        Whether the ISO image should be an efi-bootable volume.
+      '';
+    };
+
+    isoImage.makeUsbBootable = mkOption {
+      default = false;
+      description = ''
+        Whether the ISO image should be bootable from CD as well as USB.
+      '';
+    };
+
+    isoImage.efiSplashImage = mkOption {
+      default = pkgs.fetchurl {
+          url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/efi-background.png";
+          sha256 = "18lfwmp8yq923322nlb9gxrh5qikj1wsk6g5qvdh31c4h5b1538x";
+        };
+      description = ''
+        The splash image to use in the EFI bootloader.
+      '';
+    };
+
+    isoImage.splashImage = mkOption {
+      default = pkgs.fetchurl {
+          url = "https://raw.githubusercontent.com/NixOS/nixos-artwork/a9e05d7deb38a8e005a2b52575a3f59a63a4dba0/bootloader/isolinux/bios-boot.png";
+          sha256 = "1wp822zrhbg4fgfbwkr7cbkr4labx477209agzc0hr6k62fr6rxd";
+        };
+      description = ''
+        The splash image to use in the legacy-boot bootloader.
+      '';
+    };
+
+    isoImage.grubTheme = mkOption {
+      default = pkgs.nixos-grub2-theme;
+      type = types.nullOr (types.either types.path types.package);
+      description = ''
+        The grub2 theme used for UEFI boot.
+      '';
+    };
+
+    isoImage.appendToMenuLabel = mkOption {
+      default = " Installer";
+      example = " Live System";
+      description = ''
+        The string to append after the menu label for the NixOS system.
+        This will be directly appended (without whitespace) to the NixOS version
+        string, like for example if it is set to <literal>XXX</literal>:
+
+        <para><literal>NixOS 99.99-pre666XXX</literal></para>
+      '';
+    };
+
+  };
+
+  # store them in lib so we can mkImageMediaOverride the
+  # entire file system layout in installation media (only)
+  config.lib.isoFileSystems = {
+    "/" = mkImageMediaOverride
+      {
+        fsType = "tmpfs";
+        options = [ "mode=0755" ];
+      };
+
+    # Note that /dev/root is a symlink to the actual root device
+    # specified on the kernel command line, created in the stage 1
+    # init script.
+    "/iso" = mkImageMediaOverride
+      { device = "/dev/root";
+        neededForBoot = true;
+        noCheck = true;
+      };
+
+    # In stage 1, mount a tmpfs on top of /nix/store (the squashfs
+    # image) to make this a live CD.
+    "/nix/.ro-store" = mkImageMediaOverride
+      { fsType = "squashfs";
+        device = "/iso/nix-store.squashfs";
+        options = [ "loop" ];
+        neededForBoot = true;
+      };
+
+    "/nix/.rw-store" = mkImageMediaOverride
+      { fsType = "tmpfs";
+        options = [ "mode=0755" ];
+        neededForBoot = true;
+      };
+
+    "/nix/store" = mkImageMediaOverride
+      { fsType = "overlay";
+        device = "overlay";
+        options = [
+          "lowerdir=/nix/.ro-store"
+          "upperdir=/nix/.rw-store/store"
+          "workdir=/nix/.rw-store/work"
+        ];
+        depends = [
+          "/nix/.ro-store"
+          "/nix/.rw-store/store"
+          "/nix/.rw-store/work"
+        ];
+      };
+  };
+
+  config = {
+    assertions = [
+      {
+        assertion = !(stringLength config.isoImage.volumeID > 32);
+        # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor
+        # Volume Identifier can only be 32 bytes
+        message = let
+          length = stringLength config.isoImage.volumeID;
+          howmany = toString length;
+          toomany = toString (length - 32);
+        in
+        "isoImage.volumeID ${config.isoImage.volumeID} is ${howmany} characters. That is ${toomany} characters longer than the limit of 32.";
+      }
+    ];
+
+    boot.loader.grub.version = 2;
+
+    # Don't build the GRUB menu builder script, since we don't need it
+    # here and it causes a cyclic dependency.
+    boot.loader.grub.enable = false;
+
+    environment.systemPackages =  [ grubPkgs.grub2 grubPkgs.grub2_efi ]
+      ++ optional canx86BiosBoot pkgs.syslinux
+    ;
+
+    # In stage 1 of the boot, mount the CD as the root FS by label so
+    # that we don't need to know its device.  We pass the label of the
+    # root filesystem on the kernel command line, rather than in
+    # `fileSystems' below.  This allows CD-to-USB converters such as
+    # UNetbootin to rewrite the kernel command line to pass the label or
+    # UUID of the USB stick.  It would be nicer to write
+    # `root=/dev/disk/by-label/...' here, but UNetbootin doesn't
+    # recognise that.
+    boot.kernelParams =
+      [ "root=LABEL=${config.isoImage.volumeID}"
+        "boot.shell_on_fail"
+      ];
+
+    fileSystems = config.lib.isoFileSystems;
+
+    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "uas" "overlay" ];
+
+    boot.initrd.kernelModules = [ "loop" "overlay" ];
+
+    # Closures to be copied to the Nix store on the CD, namely the init
+    # script and the top-level system configuration directory.
+    isoImage.storeContents =
+      [ config.system.build.toplevel ] ++
+      optional config.isoImage.includeSystemBuildDependencies
+        config.system.build.toplevel.drvPath;
+
+    # Create the squashfs image that contains the Nix store.
+    system.build.squashfsStore = pkgs.callPackage ../../../lib/make-squashfs.nix {
+      storeContents = config.isoImage.storeContents;
+      comp = config.isoImage.squashfsCompression;
+    };
+
+    # Individual files to be included on the CD, outside of the Nix
+    # store on the CD.
+    isoImage.contents =
+      [
+        { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
+          target = "/boot/" + config.system.boot.loader.kernelFile;
+        }
+        { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
+          target = "/boot/" + config.system.boot.loader.initrdFile;
+        }
+        { source = config.system.build.squashfsStore;
+          target = "/nix-store.squashfs";
+        }
+        { source = pkgs.writeText "version" config.system.nixos.label;
+          target = "/version.txt";
+        }
+      ] ++ optionals canx86BiosBoot [
+        { source = config.isoImage.splashImage;
+          target = "/isolinux/background.png";
+        }
+        { source = pkgs.substituteAll  {
+            name = "isolinux.cfg";
+            src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
+            bootRoot = "/boot";
+          };
+          target = "/isolinux/isolinux.cfg";
+        }
+        { source = "${pkgs.syslinux}/share/syslinux";
+          target = "/isolinux";
+        }
+      ] ++ optionals config.isoImage.makeEfiBootable [
+        { source = efiImg;
+          target = "/boot/efi.img";
+        }
+        { source = "${efiDir}/EFI";
+          target = "/EFI";
+        }
+        { source = (pkgs.writeTextDir "grub/loopback.cfg" "source /EFI/boot/grub.cfg") + "/grub";
+          target = "/boot/grub";
+        }
+        { source = config.isoImage.efiSplashImage;
+          target = "/EFI/boot/efi-background.png";
+        }
+      ] ++ optionals (config.boot.loader.grub.memtest86.enable && canx86BiosBoot) [
+        { source = "${pkgs.memtest86plus}/memtest.bin";
+          target = "/boot/memtest.bin";
+        }
+      ] ++ optionals (config.isoImage.grubTheme != null) [
+        { source = config.isoImage.grubTheme;
+          target = "/EFI/boot/grub-theme";
+        }
+      ];
+
+    boot.loader.timeout = 10;
+
+    # Create the ISO image.
+    system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({
+      inherit (config.isoImage) isoName compressImage volumeID contents;
+      bootable = canx86BiosBoot;
+      bootImage = "/isolinux/isolinux.bin";
+      syslinux = if canx86BiosBoot then pkgs.syslinux else null;
+    } // optionalAttrs (config.isoImage.makeUsbBootable && canx86BiosBoot) {
+      usbBootable = true;
+      isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
+    } // optionalAttrs config.isoImage.makeEfiBootable {
+      efiBootable = true;
+      efiBootImage = "boot/efi.img";
+    });
+
+    boot.postBootCommands =
+      ''
+        # After booting, register the contents of the Nix store on the
+        # CD in the Nix database in the tmpfs.
+        ${config.nix.package.out}/bin/nix-store --load-db < /nix/store/nix-path-registration
+
+        # nixos-rebuild also requires a "system" profile and an
+        # /etc/NIXOS tag.
+        touch /etc/NIXOS
+        ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+      '';
+
+    # Add vfat support to the initrd to enable people to copy the
+    # contents of the CD to a bootable USB stick.
+    boot.initrd.supportedFilesystems = [ "vfat" ];
+
+  };
+
+}
diff --git a/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix b/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix
new file mode 100644
index 00000000000..a669d61571f
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/sd-image-aarch64-new-kernel.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  imports = [
+    ../sd-card/sd-image-aarch64-new-kernel-installer.nix
+  ];
+  config = {
+    warnings = [
+      ''
+      .../cd-dvd/sd-image-aarch64-new-kernel.nix is deprecated and will eventually be removed.
+      Please switch to .../sd-card/sd-image-aarch64-new-kernel-installer.nix, instead.
+      ''
+    ];
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
new file mode 100644
index 00000000000..76c1509b8f7
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  imports = [
+    ../sd-card/sd-image-aarch64-installer.nix
+  ];
+  config = {
+    warnings = [
+      ''
+      .../cd-dvd/sd-image-aarch64.nix is deprecated and will eventually be removed.
+      Please switch to .../sd-card/sd-image-aarch64-installer.nix, instead.
+      ''
+    ];
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
new file mode 100644
index 00000000000..6ee0eb9e9b8
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/sd-image-armv7l-multiplatform.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  imports = [
+    ../sd-card/sd-image-armv7l-multiplatform-installer.nix
+  ];
+  config = {
+    warnings = [
+      ''
+      .../cd-dvd/sd-image-armv7l-multiplatform.nix is deprecated and will eventually be removed.
+      Please switch to .../sd-card/sd-image-armv7l-multiplatform-installer.nix, instead.
+      ''
+    ];
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
new file mode 100644
index 00000000000..747440ba9c6
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/sd-image-raspberrypi.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  imports = [
+    ../sd-card/sd-image-raspberrypi-installer.nix
+  ];
+  config = {
+    warnings = [
+      ''
+      .../cd-dvd/sd-image-raspberrypi.nix is deprecated and will eventually be removed.
+      Please switch to .../sd-card/sd-image-raspberrypi-installer.nix, instead.
+      ''
+    ];
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/sd-image.nix b/nixos/modules/installer/cd-dvd/sd-image.nix
new file mode 100644
index 00000000000..e2d6dcb3fe3
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/sd-image.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+{
+  imports = [
+    ../sd-card/sd-image.nix
+  ];
+  config = {
+    warnings = [
+      ''
+      .../cd-dvd/sd-image.nix is deprecated and will eventually be removed.
+      Please switch to .../sd-card/sd-image.nix, instead.
+      ''
+    ];
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
new file mode 100644
index 00000000000..054c8c74a76
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
@@ -0,0 +1,160 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  # A dummy /etc/nixos/configuration.nix in the booted CD that
+  # rebuilds the CD's configuration (and allows the configuration to
+  # be modified, of course, providing a true live CD).  Problem is
+  # that we don't really know how the CD was built - the Nix
+  # expression language doesn't allow us to query the expression being
+  # evaluated.  So we'll just hope for the best.
+  dummyConfiguration = pkgs.writeText "configuration.nix"
+    ''
+      { config, pkgs, ... }:
+
+      { # Add your own options below, e.g.:
+        #   services.openssh.enable = true;
+        nixpkgs.config.platform = pkgs.platforms.fuloong2f_n32;
+      }
+    '';
+
+
+  pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+  # A clue for the kernel loading
+  kernelParams = pkgs.writeText "kernel-params.txt" ''
+    Kernel Parameters:
+      init=/boot/init ${toString config.boot.kernelParams}
+  '';
+
+  # System wide nixpkgs config
+  nixpkgsUserConfig = pkgs.writeText "config.nix" ''
+    pkgs:
+    {
+      platform = pkgs.platforms.fuloong2f_n32;
+    }
+  '';
+
+in
+
+{
+  imports = [ ./system-tarball.nix ];
+
+  # Disable some other stuff we don't need.
+  security.sudo.enable = false;
+
+  # Include only the en_US locale.  This saves 75 MiB or so compared to
+  # the full glibcLocales package.
+  i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"];
+
+  # Include some utilities that are useful for installing or repairing
+  # the system.
+  environment.systemPackages =
+    [ pkgs.w3m # needed for the manual anyway
+      pkgs.testdisk # useful for repairing boot problems
+      pkgs.ms-sys # for writing Microsoft boot sectors / MBRs
+      pkgs.parted
+      pkgs.ddrescue
+      pkgs.ccrypt
+      pkgs.cryptsetup # needed for dm-crypt volumes
+
+      # Some networking tools.
+      pkgs.sshfs-fuse
+      pkgs.socat
+      pkgs.screen
+      pkgs.wpa_supplicant # !!! should use the wpa module
+
+      # Hardware-related tools.
+      pkgs.sdparm
+      pkgs.hdparm
+      pkgs.dmraid
+
+      # Tools to create / manipulate filesystems.
+      pkgs.ntfsprogs # for resizing NTFS partitions
+      pkgs.btrfs-progs
+      pkgs.jfsutils
+
+      # Some compression/archiver tools.
+      pkgs.unzip
+      pkgs.zip
+      pkgs.xz
+      pkgs.dar # disk archiver
+
+      # Some editors.
+      pkgs.nvi
+      pkgs.bvi # binary editor
+      pkgs.joe
+    ];
+
+  # The initrd has to contain any module that might be necessary for
+  # mounting the CD/DVD.
+  boot.initrd.availableKernelModules =
+    [ "vfat" "reiserfs" ];
+
+  boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_10;
+  boot.kernelParams = [ "console=tty1" ];
+
+  boot.postBootCommands =
+    ''
+      mkdir -p /mnt
+
+      cp ${dummyConfiguration} /etc/nixos/configuration.nix
+    '';
+
+  # Some more help text.
+  services.getty.helpLine =
+    ''
+
+      Log in as "root" with an empty password.  ${
+        if config.services.xserver.enable then
+          "Type `start xserver' to start\nthe graphical user interface."
+        else ""
+      }
+    '';
+
+  # Include the firmware for various wireless cards.
+  networking.enableRalinkFirmware = true;
+  networking.enableIntel2200BGFirmware = true;
+
+  # To speed up further installation of packages, include the complete stdenv
+  # in the Nix store of the tarball.
+  tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ]
+    ++ [
+      {
+        object = config.system.build.bootStage2;
+        symlink = "/boot/init";
+      }
+      {
+        object = config.system.build.toplevel;
+        symlink = "/boot/system";
+      }
+    ];
+
+  tarball.contents = [
+    { source = kernelParams;
+      target = "/kernelparams.txt";
+    }
+    { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
+      target = "/boot/" + config.system.boot.loader.kernelFile;
+    }
+    { source = nixpkgsUserConfig;
+      target = "/root/.nixpkgs/config.nix";
+    }
+  ];
+
+  # Allow sshd to be started manually through "start sshd".  It should
+  # not be started by default on the installation CD because the
+  # default root password is empty.
+  services.openssh.enable = true;
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
+
+  boot.loader.grub.enable = false;
+  boot.loader.generationsDir.enable = false;
+  system.boot.loader.kernelFile = "vmlinux";
+
+  nixpkgs.config = {
+    platform = pkgs.platforms.fuloong2f_n32;
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt
new file mode 100644
index 00000000000..887bf60d0fb
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt
@@ -0,0 +1,89 @@
+Let all the files in the system tarball sit in a directory served by NFS (the
+NFS root) like this in exportfs:
+  /home/pcroot    192.168.1.0/24(rw,no_root_squash,no_all_squash)
+
+Run "exportfs -a" after editing /etc/exportfs, for the nfs server to be aware
+of the changes.
+
+Use a tftp server serving the root of boot/ (from the system tarball).
+
+In order to have PXE boot, use the boot/dhcpd.conf-example file for your dhcpd
+server, as it will point your PXE clients to pxelinux.0 from the tftp server.
+Adapt the configuration to your network.
+
+Adapt the pxelinux configuration (boot/pxelinux.cfg/default) to set the path to
+your nfrroot. If you use ip=dhcp in the kernel, the nfs server ip will be taken
+from dhcp and so you don't have to specify it.
+
+The linux in bzImage includes network drivers for some usual cards.
+
+
+QEMU Testing
+---------------
+
+You can test qemu pxe boot without having a DHCP server adapted, but having
+nfsroot, like this:
+  qemu-system-x86_64 -tftp /home/pcroot/boot -net nic -net user,bootfile=pxelinux.0 -boot n
+
+I don't know how to use NFS through the qemu '-net user' though.
+
+
+QEMU Testing with NFS root and bridged network
+-------------------------------------------------
+
+This allows testing with qemu as any other host in your LAN.
+
+Testing with the real dhcpd server requires setting up a bridge and having a
+tap device.
+  tunctl -t tap0
+  brctl addbr br0
+  brctl addif br0 eth0
+  brctl addif tap0 eth0
+  ifconfig eth0 0.0.0.0 up
+  ifconfig tap0 0.0.0.0 up
+  ifconfig br0 up # With your ip configuration
+
+Then you can run qemu:
+  qemu-system-x86_64 -boot n -net tap,ifname=tap0,script=no -net nic,model=e1000
+
+
+Using the system-tarball-pc in a chroot
+--------------------------------------------------
+
+Installation:
+  mkdir nixos-chroot && cd nixos-chroot
+  tar xf your-system-tarball.tar.xz
+  mkdir sys dev proc tmp root var run
+  mount --bind /sys sys
+  mount --bind /dev dev
+  mount --bind /proc proc
+
+Activate the system: look for a directory in nix/store similar to:
+    "/nix/store/y0d1lcj9fppli0hl3x0m0ba5g1ndjv2j-nixos-feb97bx-53f008"
+Having found it, activate that nixos system *twice*:
+  chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
+  chroot . /nix/store/SOMETHING-nixos-SOMETHING/activate
+
+This runs a 'hostname' command. Restore your old hostname with:
+  hostname OLDHOSTNAME
+
+Copy your system resolv.conf to the /etc/resolv.conf inside the chroot:
+  cp /etc/resolv.conf etc
+
+Then you can get an interactive shell in the nixos chroot. '*' means
+to run inside the chroot interactive shell
+  chroot . /bin/sh
+*  source /etc/profile
+
+Populate the nix database: that should be done in the init script if you
+had booted this nixos. Run:
+*  `grep local-cmds run/current-system/init`
+
+Then you can proceed normally subscribing to a nixos channel:
+  nix-channel --add https://nixos.org/channels/nixos-unstable
+  nix-channel --update
+
+Testing:
+  nix-env -i hello
+  which hello
+  hello
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-pc.nix b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
new file mode 100644
index 00000000000..674fb6c8a33
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
@@ -0,0 +1,163 @@
+# This module contains the basic configuration for building a NixOS
+# tarball, that can directly boot, maybe using PXE or unpacking on a fs.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+  # For PXE kernel loading
+  pxeconfig = pkgs.writeText "pxeconfig-default" ''
+    default menu.c32
+    prompt 0
+
+    label bootlocal
+      menu default
+      localboot 0
+      timeout 80
+      TOTALTIMEOUT 9000
+
+    label nixos
+      MENU LABEL ^NixOS using nfsroot
+      KERNEL bzImage
+      append ip=dhcp nfsroot=/home/pcroot init=${config.system.build.toplevel}/init rw
+
+    # I don't know how to make this boot with nfsroot (using the initrd)
+    label nixos_initrd
+      MENU LABEL NixOS booting the poor ^initrd.
+      KERNEL bzImage
+      append initrd=initrd ip=dhcp nfsroot=/home/pcroot init=${config.system.build.toplevel}/init rw
+
+    label memtest
+      MENU LABEL ^${pkgs.memtest86.name}
+      KERNEL memtest
+  '';
+
+  dhcpdExampleConfig = pkgs.writeText "dhcpd.conf-example" ''
+    # Example configuration for booting PXE.
+    allow booting;
+    allow bootp;
+
+    # Adapt this to your network configuration.
+    option domain-name "local";
+    option subnet-mask 255.255.255.0;
+    option broadcast-address 192.168.1.255;
+    option domain-name-servers 192.168.1.1;
+    option routers 192.168.1.1;
+
+    # PXE-specific configuration directives...
+    # Some BIOS don't accept slashes for paths inside the tftp servers,
+    # and will report Access Violation if they see slashes.
+    filename "pxelinux.0";
+    # For the TFTP and NFS root server. Set the IP of your server.
+    next-server 192.168.1.34;
+
+    subnet 192.168.1.0 netmask 255.255.255.0 {
+      range 192.168.1.50 192.168.1.55;
+    }
+  '';
+
+  readme = ./system-tarball-pc-readme.txt;
+
+in
+
+{
+  imports =
+    [ ./system-tarball.nix
+
+      # Profiles of this basic installation.
+      ../../profiles/all-hardware.nix
+      ../../profiles/base.nix
+      ../../profiles/installation-device.nix
+    ];
+
+  # To speed up further installation of packages, include the complete stdenv
+  # in the Nix store of the tarball.
+  tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ];
+
+  tarball.contents =
+    [ { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
+        target = "/boot/" + config.system.boot.loader.kernelFile;
+      }
+      { source = "${pkgs.syslinux}/share/syslinux/pxelinux.0";
+        target = "/boot/pxelinux.0";
+      }
+      { source = "${pkgs.syslinux}/share/syslinux/menu.c32";
+        target = "/boot/menu.c32";
+      }
+      { source = pxeconfig;
+        target = "/boot/pxelinux.cfg/default";
+      }
+      { source = readme;
+        target = "/readme.txt";
+      }
+      { source = dhcpdExampleConfig;
+        target = "/boot/dhcpd.conf-example";
+      }
+      { source = "${pkgs.memtest86}/memtest.bin";
+        # We can't leave '.bin', because pxelinux interprets this specially,
+        # and it would not load the image fine.
+        # http://forum.canardpc.com/threads/46464-0104-when-launched-via-pxe
+        target = "/boot/memtest";
+      }
+    ];
+
+  # Allow sshd to be started manually through "start sshd".  It should
+  # not be started by default on the installation CD because the
+  # default root password is empty.
+  services.openssh.enable = true;
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
+
+  # To be able to use the systemTarball to catch troubles.
+  boot.crashDump = {
+    enable = true;
+    kernelPackages = pkgs.linuxKernel.packages.linux_3_4;
+  };
+
+  # No grub for the tarball.
+  boot.loader.grub.enable = false;
+
+  /* fake entry, just to have a happy stage-1. Users
+     may boot without having stage-1 though */
+  fileSystems.fake =
+    { mountPoint = "/";
+      device = "/dev/something";
+    };
+
+  nixpkgs.config = {
+    packageOverrides = p: {
+      linux_3_4 = p.linux_3_4.override {
+        extraConfig = ''
+          # Enable drivers in kernel for most NICs.
+          E1000 y
+          # E1000E y
+          # ATH5K y
+          8139TOO y
+          NE2K_PCI y
+          ATL1 y
+          ATL1E y
+          ATL1C y
+          VORTEX y
+          VIA_RHINE y
+          R8169 y
+
+          # Enable nfs root boot
+          UNIX y # http://www.linux-mips.org/archives/linux-mips/2006-11/msg00113.html
+          IP_PNP y
+          IP_PNP_DHCP y
+          FSCACHE y
+          NFS_FS y
+          NFS_FSCACHE y
+          ROOT_NFS y
+
+          # Enable devtmpfs
+          DEVTMPFS y
+          DEVTMPFS_MOUNT y
+        '';
+      };
+    };
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
new file mode 100644
index 00000000000..458e313a3f7
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
@@ -0,0 +1,172 @@
+# This module contains the basic configuration for building a NixOS
+# tarball for the sheevaplug.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  # A dummy /etc/nixos/configuration.nix in the booted CD that
+  # rebuilds the CD's configuration (and allows the configuration to
+  # be modified, of course, providing a true live CD).  Problem is
+  # that we don't really know how the CD was built - the Nix
+  # expression language doesn't allow us to query the expression being
+  # evaluated.  So we'll just hope for the best.
+  dummyConfiguration = pkgs.writeText "configuration.nix"
+    ''
+      { config, pkgs, ... }:
+
+      {
+        # Add your own options below and run "nixos-rebuild switch".
+        # E.g.,
+        #   services.openssh.enable = true;
+      }
+    '';
+
+
+  pkgs2storeContents = l : map (x: { object = x; symlink = "none"; }) l;
+
+  # A clue for the kernel loading
+  kernelParams = pkgs.writeText "kernel-params.txt" ''
+    Kernel Parameters:
+      init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+  '';
+
+
+in
+
+{
+  imports = [ ./system-tarball.nix ];
+
+  # Disable some other stuff we don't need.
+  security.sudo.enable = false;
+
+  # Include only the en_US locale.  This saves 75 MiB or so compared to
+  # the full glibcLocales package.
+  i18n.supportedLocales = ["en_US.UTF-8/UTF-8" "en_US/ISO-8859-1"];
+
+  # Include some utilities that are useful for installing or repairing
+  # the system.
+  environment.systemPackages =
+    [ pkgs.w3m # needed for the manual anyway
+      pkgs.ddrescue
+      pkgs.ccrypt
+      pkgs.cryptsetup # needed for dm-crypt volumes
+
+      # Some networking tools.
+      pkgs.sshfs-fuse
+      pkgs.socat
+      pkgs.screen
+      pkgs.wpa_supplicant # !!! should use the wpa module
+
+      # Hardware-related tools.
+      pkgs.sdparm
+      pkgs.hdparm
+      pkgs.dmraid
+
+      # Tools to create / manipulate filesystems.
+      pkgs.btrfs-progs
+
+      # Some compression/archiver tools.
+      pkgs.unzip
+      pkgs.zip
+      pkgs.xz
+      pkgs.dar # disk archiver
+
+      # Some editors.
+      pkgs.nvi
+      pkgs.bvi # binary editor
+      pkgs.joe
+    ];
+
+  boot.loader.grub.enable = false;
+  boot.loader.generationsDir.enable = false;
+  system.boot.loader.kernelFile = "uImage";
+
+  boot.initrd.availableKernelModules =
+    [ "mvsdio" "reiserfs" "ext3" "ums-cypress" "rtc_mv" "ext4" ];
+
+  boot.postBootCommands =
+    ''
+      mkdir -p /mnt
+
+      cp ${dummyConfiguration} /etc/nixos/configuration.nix
+    '';
+
+  boot.initrd.extraUtilsCommands =
+    ''
+      copy_bin_and_libs ${pkgs.util-linux}/sbin/hwclock
+    '';
+
+  boot.initrd.postDeviceCommands =
+    ''
+      hwclock -s
+    '';
+
+  boot.kernelParams =
+    [
+      "selinux=0"
+      "console=tty1"
+      # "console=ttyS0,115200n8"  # serial console
+    ];
+
+  boot.kernelPackages = pkgs.linuxKernel.packages.linux_3_4;
+
+  boot.supportedFilesystems = [ "reiserfs" ];
+
+  /* fake entry, just to have a happy stage-1. Users
+     may boot without having stage-1 though */
+  fileSystems.fake =
+    { mountPoint = "/";
+      device = "/dev/something";
+    };
+
+  services.getty = {
+    # Some more help text.
+    helpLine = ''
+      Log in as "root" with an empty password.  ${
+        if config.services.xserver.enable then
+          "Type `start xserver' to start\nthe graphical user interface."
+        else ""
+      }
+    '';
+  };
+
+  # Setting vesa, we don't get the nvidia driver, which can't work in arm.
+  services.xserver.videoDrivers = [ "vesa" ];
+
+  documentation.nixos.enable = false;
+
+  # Include the firmware for various wireless cards.
+  networking.enableRalinkFirmware = true;
+  networking.enableIntel2200BGFirmware = true;
+
+  # To speed up further installation of packages, include the complete stdenv
+  # in the Nix store of the tarball.
+  tarball.storeContents = pkgs2storeContents [ pkgs.stdenv ];
+  tarball.contents = [
+    { source = kernelParams;
+      target = "/kernelparams.txt";
+    }
+    { source = config.boot.kernelPackages.kernel + "/" + config.system.boot.loader.kernelFile;
+      target = "/boot/" + config.system.boot.loader.kernelFile;
+    }
+    { source = pkgs.ubootSheevaplug;
+      target = "/boot/uboot";
+    }
+  ];
+
+  # Allow sshd to be started manually through "start sshd".  It should
+  # not be started by default on the installation CD because the
+  # default root password is empty.
+  services.openssh.enable = true;
+  systemd.services.openssh.wantedBy = lib.mkOverride 50 [];
+
+  # cpufrequtils fails to build on non-pc
+  powerManagement.enable = false;
+
+  nixpkgs.config = {
+    platform = pkgs.platforms.sheevaplug;
+  };
+}
diff --git a/nixos/modules/installer/cd-dvd/system-tarball.nix b/nixos/modules/installer/cd-dvd/system-tarball.nix
new file mode 100644
index 00000000000..362c555cc53
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball.nix
@@ -0,0 +1,93 @@
+# This module creates a bootable ISO image containing the given NixOS
+# configuration.  The derivation for the ISO image will be placed in
+# config.system.build.tarball.
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+  versionFile = pkgs.writeText "nixos-label" config.system.nixos.label;
+
+in
+
+{
+  options = {
+    tarball.contents = mkOption {
+      example = literalExpression ''
+        [ { source = pkgs.memtest86 + "/memtest.bin";
+            target = "boot/memtest.bin";
+          }
+        ]
+      '';
+      description = ''
+        This option lists files to be copied to fixed locations in the
+        generated ISO image.
+      '';
+    };
+
+    tarball.storeContents = mkOption {
+      example = literalExpression "[ pkgs.stdenv ]";
+      description = ''
+        This option lists additional derivations to be included in the
+        Nix store in the generated ISO image.
+      '';
+    };
+
+  };
+
+  config = {
+
+    # In stage 1 of the boot, mount the CD/DVD as the root FS by label
+    # so that we don't need to know its device.
+    fileSystems = { };
+
+    # boot.initrd.availableKernelModules = [ "mvsdio" "reiserfs" "ext3" "ext4" ];
+
+    # boot.initrd.kernelModules = [ "rtc_mv" ];
+
+    # Closures to be copied to the Nix store on the CD, namely the init
+    # script and the top-level system configuration directory.
+    tarball.storeContents =
+      [ { object = config.system.build.toplevel;
+          symlink = "/run/current-system";
+        }
+      ];
+
+    # Individual files to be included on the CD, outside of the Nix
+    # store on the CD.
+    tarball.contents =
+      [ { source = config.system.build.initialRamdisk + "/" + config.system.boot.loader.initrdFile;
+          target = "/boot/" + config.system.boot.loader.initrdFile;
+        }
+        { source = versionFile;
+          target = "/nixos-version.txt";
+        }
+      ];
+
+    # Create the tarball
+    system.build.tarball = import ../../../lib/make-system-tarball.nix {
+      inherit (pkgs) stdenv closureInfo pixz;
+
+      inherit (config.tarball) contents storeContents;
+    };
+
+    boot.postBootCommands =
+      ''
+        # After booting, register the contents of the Nix store on the
+        # CD in the Nix database in the tmpfs.
+        if [ -f /nix-path-registration ]; then
+          ${config.nix.package.out}/bin/nix-store --load-db < /nix-path-registration &&
+          rm /nix-path-registration
+        fi
+
+        # nixos-rebuild also requires a "system" profile and an
+        # /etc/NIXOS tag.
+        touch /etc/NIXOS
+        ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+      '';
+
+  };
+
+}