summary refs log tree commit diff
path: root/nixos/modules/installer
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2013-10-10 13:28:20 +0200
commit5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010 (patch)
treea6c0f605be6de3f372ae69905b331f9f75452da7 /nixos/modules/installer
parent6070bc016bd2fd945b04347e25cfd3738622d2ac (diff)
downloadnixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.gz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.bz2
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.lz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.xz
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.zst
nixpkgs-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.zip
Move all of NixOS to nixos/ in preparation of the repository merge
Diffstat (limited to 'nixos/modules/installer')
-rw-r--r--nixos/modules/installer/cd-dvd/channel.nix43
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-base.nix37
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-efi.nix14
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-graphical.nix30
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix8
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-minimal.nix11
-rw-r--r--nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix8
-rw-r--r--nixos/modules/installer/cd-dvd/iso-image.nix315
-rw-r--r--nixos/modules/installer/cd-dvd/live-dvd.nix78
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix164
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc-readme.txt89
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-pc.nix164
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix176
-rw-r--r--nixos/modules/installer/cd-dvd/system-tarball.nix92
-rw-r--r--nixos/modules/installer/scan/detected.nix13
-rw-r--r--nixos/modules/installer/scan/not-detected.nix9
-rw-r--r--nixos/modules/installer/tools/get-version-suffix29
-rw-r--r--nixos/modules/installer/tools/nixos-build-vms/build-vms.nix9
-rw-r--r--nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh62
-rw-r--r--nixos/modules/installer/tools/nixos-checkout.nix55
-rw-r--r--nixos/modules/installer/tools/nixos-gen-seccure-keys.sh13
-rw-r--r--nixos/modules/installer/tools/nixos-hardware-scan.pl248
-rw-r--r--nixos/modules/installer/tools/nixos-install.sh238
-rw-r--r--nixos/modules/installer/tools/nixos-option.sh395
-rw-r--r--nixos/modules/installer/tools/nixos-rebuild.sh222
-rw-r--r--nixos/modules/installer/tools/nixos-version.sh2
-rw-r--r--nixos/modules/installer/tools/tools.nix112
-rw-r--r--nixos/modules/installer/virtualbox-demo.nix19
28 files changed, 2655 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..8126ce46dd9
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/channel.nix
@@ -0,0 +1,43 @@
+# Provide an initial copy of the NixOS channel so that the user
+# doesn't need to run "nix-channel --update" first.
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  # 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.
+  channelSources = pkgs.runCommand "nixos-${config.system.nixosVersion}"
+    { expr = builtins.readFile ../../../lib/channel-expr.nix; }
+    ''
+      mkdir -p $out/nixos
+      cp -prd ${cleanSource ../../..} $out/nixos/nixos
+      cp -prd ${cleanSource <nixpkgs>} $out/nixos/nixpkgs
+      chmod -R u+w $out/nixos/nixos
+      echo -n ${config.system.nixosVersion} > $out/nixos/nixos/.version
+      echo -n "" > $out/nixos/nixos/.version-suffix
+      echo "$expr" > $out/nixos/default.nix
+    '';
+
+in
+
+{
+  # Provide the NixOS/Nixpkgs sources in /etc/nixos.  This is required
+  # for nixos-install.
+  boot.postBootCommands =
+    ''
+      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.environment.nix}/bin/nix-env -p /nix/var/nix/profiles/per-user/root/channels \
+          -i ${channelSources} --quiet --option 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..999871ab074
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-base.nix
@@ -0,0 +1,37 @@
+# This module contains the basic configuration for building a NixOS
+# installation CD.
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+{
+  imports =
+    [ ./channel.nix
+      ./iso-image.nix
+
+      # Profiles of this basic installation CD.
+      ../../profiles/all-hardware.nix
+      ../../profiles/base.nix
+      ../../profiles/installation-device.nix
+    ];
+
+  # ISO naming.
+  isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixosVersion}-${pkgs.stdenv.system}.iso";
+
+  isoImage.volumeID = substring 0 32 "NIXOS_${config.system.nixosVersion}";
+
+  # Make the installer more likely to succeed in low memory
+  # environments.  The kernel's overcommit heustistics bite us
+  # fairly often, preventing processes such as nix-worker or
+  # download-using-manifests.pl from forking even if there is
+  # plenty of free memory.
+  boot.kernel.sysctl."vm.overcommit_memory" = "1";
+
+  # To speed up installation a little bit, include the complete stdenv
+  # in the Nix store on the CD.
+  isoImage.storeContents = [ pkgs.stdenv pkgs.busybox ];
+
+  # Add Memtest86+ to the CD.
+  boot.loader.grub.memtest86 = true;
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-efi.nix b/nixos/modules/installer/cd-dvd/installation-cd-efi.nix
new file mode 100644
index 00000000000..4aa788feeae
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-efi.nix
@@ -0,0 +1,14 @@
+{ config, pkgs, ... }:
+
+{
+  # Move into base image once using 3.10 or later
+
+  require = [ ./installation-cd-minimal.nix ];
+
+  boot.kernelPackages = pkgs.linuxPackages_3_10;
+
+  # Get a console as soon as the initrd loads fbcon on EFI boot
+  boot.initrd.kernelModules = [ "fbcon" ];
+
+  isoImage.makeEfiBootable = true;
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix b/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix
new file mode 100644
index 00000000000..debf3e7db90
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-graphical.nix
@@ -0,0 +1,30 @@
+# This module defines a NixOS installation CD that contains X11 and
+# KDE 4.
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+{
+  imports = [ ./installation-cd-base.nix ../../profiles/graphical.nix ];
+
+  # Provide wicd for easy wireless configuration.
+  #networking.wicd.enable = true;
+
+  # KDE complains if power management is disabled (to be precise, if
+  # there is no power management backend such as upower).
+  powerManagement.enable = true;
+
+  # Don't start the X server by default.
+  services.xserver.autorun = mkForce false;
+
+  # Auto-login as root.
+  services.xserver.displayManager.kdm.extraConfig =
+    ''
+      [X-*-Core]
+      AllowRootLogin=true
+      AutoLoginEnable=true
+      AutoLoginUser=root
+      AutoLoginPass=""
+    '';
+}
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..38d02ffd162
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal-new-kernel.nix
@@ -0,0 +1,8 @@
+{ config, pkgs, ... }:
+
+{
+  imports = [ ./installation-cd-minimal.nix ];
+
+  boot.kernelPackages = pkgs.linuxPackages_3_10;
+  boot.vesa = false;
+}
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..a7498906a86
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix
@@ -0,0 +1,11 @@
+# This module defines a small NixOS installation CD.  It does not
+# contain any graphical stuff.
+
+{ config, pkgs, ... }:
+
+{
+  imports =
+    [ ./installation-cd-base.nix
+      ../../profiles/minimal.nix
+    ];
+}
diff --git a/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix b/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix
new file mode 100644
index 00000000000..93bcbf00b25
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/installation-cd-new-kernel.nix
@@ -0,0 +1,8 @@
+{ config, pkgs, ... }:
+
+{
+  imports = [ ./installation-cd-graphical.nix ];
+
+  boot.kernelPackages = pkgs.linuxPackages_3_10;
+  boot.vesa = 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..de9728d677c
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/iso-image.nix
@@ -0,0 +1,315 @@
+# 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, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  # The Grub image.
+  grubImage = pkgs.runCommand "grub_eltorito" {}
+    ''
+      ${pkgs.grub2}/bin/grub-mkimage -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
+      cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
+    ''; # */
+
+
+  # The configuration file for Grub.
+  grubCfg =
+    ''
+      set default=${builtins.toString config.boot.loader.grub.default}
+      set timeout=${builtins.toString config.boot.loader.grub.timeout}
+
+      if loadfont /boot/grub/unicode.pf2; then
+        set gfxmode=640x480
+        insmod gfxterm
+        insmod vbe
+        terminal_output gfxterm
+
+        insmod png
+        if background_image /boot/grub/splash.png; then
+          set color_normal=white/black
+          set color_highlight=black/white
+        else
+          set menu_color_normal=cyan/blue
+          set menu_color_highlight=white/blue
+        fi
+
+      fi
+
+      ${config.boot.loader.grub.extraEntries}
+    '';
+
+
+  # The efi boot image
+  efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools ]; }
+    ''
+      #Let's hope 10M is enough
+      dd bs=2048 count=5120 if=/dev/zero of="$out"
+      ${pkgs.dosfstools}/sbin/mkfs.vfat "$out"
+      mmd -i "$out" efi
+      mmd -i "$out" efi/boot
+      mmd -i "$out" efi/nixos
+      mmd -i "$out" loader
+      mmd -i "$out" loader/entries
+      mcopy -v -i "$out" \
+        ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi \
+        ::efi/boot/boot${targetArch}.efi
+      mcopy -v -i "$out" \
+        ${config.boot.kernelPackages.kernel}/bzImage ::bzImage
+      mcopy -v -i "$out" \
+        ${config.system.build.initialRamdisk}/initrd ::efi/nixos/initrd
+      echo "title NixOS LiveCD" > boot-params
+      echo "linux /bzImage" >> boot-params
+      echo "initrd /efi/nixos/initrd" >> boot-params
+      echo "options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" >> boot-params
+      mcopy -v -i "$out" boot-params ::loader/entries/nixos-livecd.conf
+      echo "default nixos-livecd" > boot-params
+      echo "timeout 5" >> boot-params
+      mcopy -v -i "$out" boot-params ::loader/loader.conf
+    '';
+
+  targetArch = if pkgs.stdenv.isi686 then
+    "ia32"
+  else if pkgs.stdenv.isx86_64 then
+    "x64"
+  else
+    throw "Unsupported architecture";
+
+in
+
+{
+  options = {
+
+    isoImage.isoName = mkOption {
+      default = "${config.isoImage.isoName}.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>bzip2</command>.
+      '';
+    };
+
+    isoImage.volumeID = mkOption {
+      default = "NIXOS_BOOT_CD";
+      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 =
+        [ { 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 = [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;
+      example = true;
+      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 on non-existent network connection.
+      '';
+    };
+
+    isoImage.makeEfiBootable = mkOption {
+      default = false;
+      description = ''
+        Whether the ISO image should be an efi-bootable volume.
+      '';
+    };
+
+
+  };
+
+
+  config = {
+
+    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;
+
+    # !!! Hack - attributes expected by other modules.
+    system.boot.loader.kernelFile = "bzImage";
+    environment.systemPackages = [ pkgs.grub2 ];
+
+    # 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}" ];
+
+    # 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.
+    fileSystems."/".device = "/dev/root";
+
+    fileSystems."/nix/store" =
+      { fsType = "squashfs";
+        device = "/nix-store.squashfs";
+        options = "loop";
+      };
+
+    boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ];
+
+    boot.initrd.kernelModules = [ "loop" ];
+
+    # In stage 1, mount a tmpfs on top of / (the ISO image) and
+    # /nix/store (the squashfs image) to make this a live CD.
+    boot.initrd.postMountCommands =
+      ''
+        mkdir -p /unionfs-chroot/ro-root
+        mount --rbind $targetRoot /unionfs-chroot/ro-root
+
+        mkdir /unionfs-chroot/rw-root
+        mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-root
+        mkdir /mnt-root-union
+        unionfs -o allow_other,cow,chroot=/unionfs-chroot,max_files=32768 /rw-root=RW:/ro-root=RO /mnt-root-union
+        oldTargetRoot=$targetRoot
+        targetRoot=/mnt-root-union
+
+        mkdir /unionfs-chroot/rw-store
+        mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-store
+        mkdir -p $oldTargetRoot/nix/store
+        unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768 /rw-store=RW:/ro-root/nix/store=RO /mnt-root-union/nix/store
+      '';
+
+    # 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 = import ../../../lib/make-squashfs.nix {
+      inherit (pkgs) stdenv squashfsTools perl pathsFromGraph;
+      storeContents = config.isoImage.storeContents;
+    };
+
+    # Individual files to be included on the CD, outside of the Nix
+    # store on the CD.
+    isoImage.contents =
+      [ { source = grubImage;
+          target = "/boot/grub/grub_eltorito";
+        }
+        { source = pkgs.substituteAll  {
+            name = "grub.cfg";
+            src = pkgs.writeText "grub.cfg-in" grubCfg;
+            bootRoot = "/boot";
+          };
+          target = "/boot/grub/grub.cfg";
+        }
+        { source = config.boot.kernelPackages.kernel + "/bzImage";
+          target = "/boot/bzImage";
+        }
+        { source = config.system.build.initialRamdisk + "/initrd";
+          target = "/boot/initrd";
+        }
+        { source = "${pkgs.grub2}/share/grub/unicode.pf2";
+          target = "/boot/grub/unicode.pf2";
+        }
+        { source = config.boot.loader.grub.splashImage;
+          target = "/boot/grub/splash.png";
+        }
+        { source = config.system.build.squashfsStore;
+          target = "/nix-store.squashfs";
+        }
+        { # Quick hack: need a mount point for the store.
+          source = pkgs.runCommand "empty" {} "mkdir -p $out";
+          target = "/nix/store";
+        }
+      ] ++ optionals config.isoImage.makeEfiBootable [
+        { source = efiImg;
+          target = "/boot/efi.img";
+        }
+      ] ++ mapAttrsToList (n: v: { source = v; target = "/boot/${n}"; }) config.boot.loader.grub.extraFiles;
+
+    # The Grub menu.
+    boot.loader.grub.extraEntries =
+      ''
+        menuentry "NixOS ${config.system.nixosVersion} Installer" {
+          linux /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
+          initrd /boot/initrd
+        }
+
+        menuentry "Boot from hard disk" {
+          set root=(hd0)
+          chainloader +1
+        }
+      '';
+
+    boot.loader.grub.timeout = 10;
+
+    # Create the ISO image.
+    system.build.isoImage = import ../../../lib/make-iso9660-image.nix ({
+      inherit (pkgs) stdenv perl cdrkit pathsFromGraph;
+
+      inherit (config.isoImage) isoName compressImage volumeID contents;
+
+      bootable = true;
+      bootImage = "/boot/grub/grub_eltorito";
+    } // 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.environment.nix}/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.environment.nix}/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. Need unionfs-fuse for union mounts
+    boot.initrd.supportedFilesystems = [ "vfat" "unionfs-fuse" ];
+
+  };
+
+}
diff --git a/nixos/modules/installer/cd-dvd/live-dvd.nix b/nixos/modules/installer/cd-dvd/live-dvd.nix
new file mode 100644
index 00000000000..e57be6d442e
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/live-dvd.nix
@@ -0,0 +1,78 @@
+{ config, pkgs, ... }:
+
+{
+  imports = [ ./installation-cd-base.nix ];
+
+  # Build the build-time dependencies of this configuration on the DVD
+  # to speed up installation.
+  isoImage.storeContents = [ config.system.build.toplevel.drvPath ];
+
+  # Include lots of packages.
+  environment.systemPackages =
+    [ pkgs.utillinuxCurses
+      pkgs.upstartJobControl
+      pkgs.iproute
+      pkgs.bc
+      pkgs.fuse
+      pkgs.zsh
+      pkgs.sqlite
+      pkgs.gnupg
+      pkgs.manpages
+      pkgs.pinentry
+      pkgs.screen
+      pkgs.patch
+      pkgs.which
+      pkgs.diffutils
+      pkgs.file
+      pkgs.irssi
+      pkgs.mcabber
+      pkgs.mutt
+      pkgs.emacs
+      pkgs.vimHugeX
+      pkgs.bvi
+      pkgs.ddrescue
+      pkgs.cdrkit
+      pkgs.btrfsProgs
+      pkgs.xfsprogs
+      pkgs.jfsutils
+      pkgs.jfsrec
+      pkgs.ntfs3g
+      pkgs.subversion16
+      pkgs.monotone
+      pkgs.git
+      pkgs.darcs
+      pkgs.mercurial
+      pkgs.bazaar
+      pkgs.cvs
+      pkgs.pciutils
+      pkgs.hddtemp
+      pkgs.sdparm
+      pkgs.hdparm
+      pkgs.usbutils
+      pkgs.openssh
+      pkgs.lftp
+      pkgs.w3m
+      pkgs.openssl
+      pkgs.ncat
+      pkgs.lynx
+      pkgs.wget
+      pkgs.elinks
+      pkgs.socat
+      pkgs.squid
+      pkgs.unrar
+      pkgs.zip
+      pkgs.unzip
+      pkgs.lzma
+      pkgs.cabextract
+      pkgs.cpio
+      pkgs.lsof
+      pkgs.ltrace
+      pkgs.perl
+      pkgs.python
+      pkgs.ruby
+      pkgs.guile
+      pkgs.clisp
+      pkgs.tcl
+    ];
+
+}
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..85356118ce6
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-fuloong2f.nix
@@ -0,0 +1,164 @@
+{ config, pkgs, ... }:
+
+with pkgs.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 systemConfig=/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.subversion # for nixos-checkout
+      pkgs.w3m # needed for the manual anyway
+      pkgs.testdisk # useful for repairing boot problems
+      pkgs.mssys # for writing Microsoft boot sectors / MBRs
+      pkgs.parted
+      pkgs.ddrescue
+      pkgs.ccrypt
+      pkgs.cryptsetup # needed for dm-crypt volumes
+
+      # Some networking tools.
+      pkgs.sshfsFuse
+      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.btrfsProgs
+      pkgs.jfsutils
+      pkgs.jfsrec
+
+      # Some compression/archiver tools.
+      pkgs.unrar
+      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.linuxPackages_3_10;
+  boot.kernelParams = [ "console=tty1" ];
+
+  boot.postBootCommands =
+    ''
+      mkdir -p /mnt
+
+      cp ${dummyConfiguration} /etc/nixos/configuration.nix
+    '';
+
+  # Some more help text.
+  services.mingetty.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;
+
+  jobs.openssh.startOn = pkgs.lib.mkOverrideTemplate 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..8f0a8d355c6
--- /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 http://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..7619f074b74
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-pc.nix
@@ -0,0 +1,164 @@
+# This module contains the basic configuration for building a NixOS
+# tarball, that can directly boot, maybe using PXE or unpacking on a fs.
+
+{ config, pkgs, ... }:
+
+with pkgs.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 systemConfig=${config.system.build.toplevel} 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 systemConfig=${config.system.build.toplevel} 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;
+  jobs.openssh.startOn = pkgs.lib.mkOverrideTemplate 50 {} "";
+
+  # To be able to use the systemTarball to catch troubles.
+  boot.crashDump = {
+    enable = true;
+    kernelPackages = pkgs.linuxPackages_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 = [
+    { mountPoint = "/";
+      device = "/dev/something";
+      }
+  ];
+
+  nixpkgs.config = {
+    packageOverrides = p: rec {
+      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..20fe4de2cd8
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball-sheevaplug.nix
@@ -0,0 +1,176 @@
+# This module contains the basic configuration for building a NixOS
+# tarball for the sheevaplug.
+
+{ config, pkgs, ... }:
+
+with pkgs.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.subversion # for nixos-checkout
+      pkgs.w3m # needed for the manual anyway
+      pkgs.ddrescue
+      pkgs.ccrypt
+      pkgs.cryptsetup # needed for dm-crypt volumes
+
+      # Some networking tools.
+      pkgs.sshfsFuse
+      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.btrfsProgs
+
+      # Some compression/archiver tools.
+      pkgs.unrar
+      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" "mmc_block" "reiserfs" "ext3" "ums-cypress" "rtc_mv"
+      "ext4" ];
+
+  boot.postBootCommands =
+    ''
+      mkdir -p /mnt
+
+      cp ${dummyConfiguration} /etc/nixos/configuration.nix
+    '';
+
+  boot.initrd.extraUtilsCommands =
+    ''
+      cp ${pkgs.utillinux}/sbin/hwclock $out/bin
+    '';
+
+  boot.initrd.postDeviceCommands =
+    ''
+      hwclock -s
+    '';
+
+  boot.kernelParams =
+    [
+      "selinux=0"
+      "console=tty1"
+      # "console=ttyS0,115200n8"  # serial console
+    ];
+
+  boot.kernelPackages = pkgs.linuxPackages_3_4;
+
+  boot.supportedFilesystems = [ "reiserfs" ];
+
+  /* fake entry, just to have a happy stage-1. Users
+     may boot without having stage-1 though */
+  fileSystems = [
+    { mountPoint = "/";
+      device = "/dev/something";
+      }
+  ];
+
+  services.mingetty = {
+    # 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.videoDriver = "vesa";
+  services.xserver.videoDrivers = [];
+  services.nixosManual.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;
+  jobs.openssh.startOn = pkgs.lib.mkOverrideTemplate 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..6bf8eebdac5
--- /dev/null
+++ b/nixos/modules/installer/cd-dvd/system-tarball.nix
@@ -0,0 +1,92 @@
+# 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, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+
+  versionFile = pkgs.writeText "nixos-version" config.system.nixosVersion;
+
+in
+
+{
+  options = {
+    tarball.contents = mkOption {
+      example =
+        [ { 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 = [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" "mmc_block" "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 + "/initrd";
+          target = "/boot/initrd";
+        }
+        { source = versionFile;
+          target = "/nixos-version.txt";
+        }
+      ];
+
+    # Create the tarball
+    system.build.tarball = import ../../../lib/make-system-tarball.nix {
+      inherit (pkgs) stdenv perl xz pathsFromGraph;
+
+      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.environment.nix}/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.environment.nix}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+      '';
+
+  };
+
+}
diff --git a/nixos/modules/installer/scan/detected.nix b/nixos/modules/installer/scan/detected.nix
new file mode 100644
index 00000000000..09d04608e68
--- /dev/null
+++ b/nixos/modules/installer/scan/detected.nix
@@ -0,0 +1,13 @@
+# List all devices which are detected by nixos-hardware-scan.
+# Common devices are enabled by default.
+{config, pkgs, ...}:
+
+with pkgs.lib;
+
+{
+  config = mkDefault {
+    # Wireless card firmware
+    networking.enableIntel2200BGFirmware = true;
+    networking.enableIntel3945ABGFirmware = true;
+  };
+}
diff --git a/nixos/modules/installer/scan/not-detected.nix b/nixos/modules/installer/scan/not-detected.nix
new file mode 100644
index 00000000000..814858fdffd
--- /dev/null
+++ b/nixos/modules/installer/scan/not-detected.nix
@@ -0,0 +1,9 @@
+# List all devices which are _not_ detected by nixos-hardware-scan.
+# Common devices are enabled by default.
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+{
+  hardware.enableAllFirmware = true;
+}
diff --git a/nixos/modules/installer/tools/get-version-suffix b/nixos/modules/installer/tools/get-version-suffix
new file mode 100644
index 00000000000..76cec8d5dae
--- /dev/null
+++ b/nixos/modules/installer/tools/get-version-suffix
@@ -0,0 +1,29 @@
+getVersion() {
+    local dir="$1"
+    rev=
+    if [ -e "$dir/.git" ]; then
+        if [ -z "$(type -P git)" ]; then
+            echo "warning: Git not found; cannot figure out revision of $dir" >&2
+            return
+        fi
+        cd "$dir"
+        rev=$(git rev-parse --short HEAD)
+        if git describe --always --dirty | grep -q dirty; then
+            rev+=M
+        fi
+    fi
+}
+
+if nixos=$(nix-instantiate --find-file nixos "$@"); then
+    getVersion $nixos
+    if [ -n "$rev" ]; then
+        suffix="pre-$rev"
+        if nixpkgs=$(nix-instantiate --find-file nixpkgs "$@"); then
+            getVersion $nixpkgs
+            if [ -n "$rev" ]; then
+                suffix+="-$rev"
+            fi
+        fi
+        echo $suffix
+    fi
+fi
diff --git a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
new file mode 100644
index 00000000000..5e77b701ff5
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix
@@ -0,0 +1,9 @@
+{ system ? builtins.currentSystem
+, networkExpr
+}:
+
+let nodes = import networkExpr; in
+
+with import ../../../../lib/testing.nix { inherit system; };
+
+(complete { inherit nodes; testScript = ""; }).driver
diff --git a/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh
new file mode 100644
index 00000000000..0a6e8b920a1
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh
@@ -0,0 +1,62 @@
+#! @shell@ -e
+
+# Shows the usage of this command to the user
+
+showUsage()
+{
+    echo "Usage: $0 network_expr"
+    echo "Options:"
+    echo
+    echo "--no-out-link   Do not create a 'result' symlink"
+    echo "--show-trace    Shows the output trace"
+    echo "-h,--help       Shows the usage of this command"
+}
+
+# Parse valid argument options
+
+PARAMS=`getopt -n $0 -o h -l no-out-link,show-trace,help -- "$@"`
+
+if [ $? != 0 ]
+then
+    showUsage
+    exit 1
+fi
+
+eval set -- "$PARAMS"
+
+# Evaluate valid options
+
+while [ "$1" != "--" ]
+do
+    case "$1" in
+	--no-out-link)
+	    noOutLinkArg="--no-out-link"
+	    ;;
+	--show-trace)
+	    showTraceArg="--show-trace"
+	    ;;
+	-h|--help)
+	    showUsage
+	    exit 0
+	    ;;
+    esac
+    
+    shift
+done
+
+shift
+
+# Validate the given options
+
+if [ "$1" = "" ]
+then
+    echo "ERROR: A network expression must be specified!" >&2
+    exit 1
+else
+    networkExpr=$(readlink -f $1)
+fi
+
+# Build a network of VMs
+
+nix-build '<nixos/modules/installer/tools/nixos-build-vms/build-vms.nix>' \
+    --argstr networkExpr $networkExpr $noOutLinkArg $showTraceArg
diff --git a/nixos/modules/installer/tools/nixos-checkout.nix b/nixos/modules/installer/tools/nixos-checkout.nix
new file mode 100644
index 00000000000..1a734ca5eeb
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-checkout.nix
@@ -0,0 +1,55 @@
+# This module generates the nixos-checkout script, which replaces the
+# NixOS and Nixpkgs source trees in /etc/nixos/{nixos,nixpkgs} with
+# Git checkouts.
+
+{config, pkgs, ...}:
+
+with pkgs.lib;
+
+let
+
+  nixosCheckout = pkgs.substituteAll {
+    name = "nixos-checkout";
+    dir = "bin";
+    isExecutable = true;
+    src = pkgs.writeScript "nixos-checkout"
+      ''
+        #! ${pkgs.stdenv.shell} -e
+
+        if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
+          echo "Usage: `basename $0` [PREFIX]. See NixOS Manual for more info."
+          exit 0
+        fi        
+
+        prefix="$1"
+        if [ -z "$prefix" ]; then prefix=/etc/nixos; fi
+        mkdir -p "$prefix"
+        cd "$prefix"
+
+        if [ -z "$(type -P git)" ]; then
+            echo "installing Git..."
+            nix-env -iA nixos.pkgs.git || nix-env -i git
+        fi
+
+        # Move any old nixos or nixpkgs directories out of the way.
+        backupTimestamp=$(date "+%Y%m%d%H%M%S")
+
+        if [ -e nixos -a ! -e nixos/.git ]; then
+            mv nixos nixos-$backupTimestamp
+        fi
+
+        if [ -e nixpkgs -a ! -e nixpkgs/.git ]; then
+            mv nixpkgs nixpkgs-$backupTimestamp
+        fi
+
+        # Check out the NixOS and Nixpkgs sources.
+        git clone git://github.com/NixOS/nixos.git nixos
+        git clone git://github.com/NixOS/nixpkgs.git nixpkgs
+      '';
+   };
+
+in
+
+{
+  environment.systemPackages = [ nixosCheckout ];
+}
diff --git a/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh b/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh
new file mode 100644
index 00000000000..a97eef672f7
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh
@@ -0,0 +1,13 @@
+#! @shell@ -e
+
+mkdir -p /var/elliptic-keys
+chmod 0755 /var/elliptic-keys
+cd /var/elliptic-keys
+touch private
+chmod 0700 private
+dd if=/dev/urandom bs=128 count=1 of=private
+chmod 0500 private
+public=$(seccure-key -F private 2>&1)
+echo ${public#*The public key is: } > public
+chmod 0555 public
+
diff --git a/nixos/modules/installer/tools/nixos-hardware-scan.pl b/nixos/modules/installer/tools/nixos-hardware-scan.pl
new file mode 100644
index 00000000000..3204f3d4051
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-hardware-scan.pl
@@ -0,0 +1,248 @@
+#! @perl@/bin/perl -w
+
+use File::Spec;
+use File::Basename;
+
+
+my @attrs = ();
+my @kernelModules = ();
+my @initrdKernelModules = ();
+my @modulePackages = ();
+my @imports = ("<nixos/modules/installer/scan/not-detected.nix>");
+
+
+sub debug {
+    return unless defined $ENV{"DEBUG"};
+    print STDERR @_;
+}
+
+
+# Read a file, returning undef if the file cannot be opened.
+sub readFile {
+    my $filename = shift;
+    my $res;
+    if (open FILE, "<$filename") {
+        my $prev = $/;
+        undef $/;
+        $res = <FILE>;
+        $/ = $prev;
+        close FILE;
+        chomp $res;
+    }
+    return $res;
+}
+
+
+my $cpuinfo = readFile "/proc/cpuinfo";
+
+
+sub hasCPUFeature {
+    my $feature = shift;
+    return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m;
+}
+
+
+# Detect the number of CPU cores.
+my $cpus = scalar (grep {/^processor\s*:/} (split '\n', $cpuinfo));
+
+
+# Virtualization support?
+push @kernelModules, "kvm-intel" if hasCPUFeature "vmx";
+push @kernelModules, "kvm-amd" if hasCPUFeature "svm";
+
+
+# Look at the PCI devices and add necessary modules.  Note that most
+# modules are auto-detected so we don't need to list them here.
+# However, some are needed in the initrd to boot the system.
+
+my $videoDriver;
+
+sub pciCheck {
+    my $path = shift;
+    my $vendor = readFile "$path/vendor";
+    my $device = readFile "$path/device";
+    my $class = readFile "$path/class";
+    
+    my $module;
+    if (-e "$path/driver/module") {
+        $module = basename `readlink -f $path/driver/module`;
+        chomp $module;
+    }
+    
+    debug "$path: $vendor $device $class";
+    debug " $module" if defined $module;
+    debug "\n";
+
+    if (defined $module) {
+        # See the bottom of http://pciids.sourceforge.net/pci.ids for
+        # device classes.
+        if (# Mass-storage controller.  Definitely important.
+            $class =~ /^0x01/ ||
+
+            # Firewire controller.  A disk might be attached.
+            $class =~ /^0x0c00/ ||
+
+            # USB controller.  Needed if we want to use the
+            # keyboard when things go wrong in the initrd.
+            $class =~ /^0x0c03/
+            )
+        {
+            push @initrdKernelModules, $module;
+        }
+    }
+
+    # broadcom STA driver (wl.ko)
+    # list taken from http://www.broadcom.com/docs/linux_sta/README.txt
+    if ($vendor eq "0x14e4" &&
+        ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" ||
+         $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" ||
+         $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" ||
+         $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" ||
+         $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" ) )
+     {
+        push @modulePackages, "config.boot.kernelPackages.broadcom_sta";
+        push @kernelModules, "wl";
+     }
+
+    # Can't rely on $module here, since the module may not be loaded
+    # due to missing firmware.  Ideally we would check modules.pcimap
+    # here.
+    push @attrs, "networking.enableIntel2200BGFirmware = true;" if
+        $vendor eq "0x8086" &&
+        ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" ||
+         $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224");
+
+    push @attrs, "networking.enableIntel3945ABGFirmware = true;" if
+        $vendor eq "0x8086" &&
+        ($device eq "0x4229" || $device eq "0x4230" ||
+         $device eq "0x4222" || $device eq "0x4227");
+
+    # Assume that all NVIDIA cards are supported by the NVIDIA driver.
+    # There may be exceptions (e.g. old cards).
+    $videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/;
+}
+
+foreach my $path (glob "/sys/bus/pci/devices/*") {
+    pciCheck $path;
+}
+
+
+# Idem for USB devices.
+
+sub usbCheck {
+    my $path = shift;
+    my $class = readFile "$path/bInterfaceClass";
+    my $subclass = readFile "$path/bInterfaceSubClass";
+    my $protocol = readFile "$path/bInterfaceProtocol";
+
+    my $module;
+    if (-e "$path/driver/module") {
+        $module = basename `readlink -f $path/driver/module`;
+        chomp $module;
+    }
+    
+    debug "$path: $class $subclass $protocol";
+    debug " $module" if defined $module;
+    debug "\n";
+ 
+    if (defined $module) {
+        if (# Mass-storage controller.  Definitely important.
+            $class eq "08" ||
+
+            # Keyboard.  Needed if we want to use the
+            # keyboard when things go wrong in the initrd.
+            ($class eq "03" && $protocol eq "01")
+            )
+        {
+            push @initrdKernelModules, $module;
+        }
+    }
+}
+
+foreach my $path (glob "/sys/bus/usb/devices/*") {
+    if (-e "$path/bInterfaceClass") {
+        usbCheck $path;
+    }
+}
+
+
+# Add the modules for all block devices.
+
+foreach my $path (glob "/sys/class/block/*") {
+    my $module;
+    if (-e "$path/device/driver/module") {
+        $module = basename `readlink -f $path/device/driver/module`;
+        chomp $module;
+        push @initrdKernelModules, $module;
+    }
+}
+
+
+if ($videoDriver) {
+    push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];";
+}
+
+
+# Check if we're a VirtualBox guest.  If so, enable the guest
+# additions.
+my $dmi = `@dmidecode@/sbin/dmidecode`;
+if ($dmi =~ /Manufacturer: innotek/) {
+    push @attrs, "services.virtualbox.enable = true;"
+}
+
+
+# Generate the configuration file.
+
+sub removeDups {
+    my %seen;
+    my @res = ();
+    foreach my $s (@_) {
+        if (!defined $seen{$s}) {
+            $seen{$s} = "";
+            push @res, $s;
+        }
+    }
+    return @res;
+}
+
+sub toNixExpr {
+    my $res = "";
+    foreach my $s (@_) {
+        $res .= " \"$s\"";
+    }
+    return $res;
+}
+
+sub multiLineList {
+    my $indent = shift;
+    my $res = "";
+    $res = "\n" if scalar @_ > 0;
+    foreach my $s (@_) {
+        $res .= "$indent$s\n";
+    }
+    return $res;
+}
+
+my $initrdKernelModules = toNixExpr(removeDups @initrdKernelModules);
+my $kernelModules = toNixExpr(removeDups @kernelModules);
+my $modulePackages = toNixExpr(removeDups @modulePackages);
+my $attrs = multiLineList("  ", removeDups @attrs);
+my $imports = multiLineList("    ", removeDups @imports);
+
+
+print <<EOF ;
+# This is a generated file.  Do not modify!
+# Make changes to /etc/nixos/configuration.nix instead.
+{ config, pkgs, ... }:
+
+{
+  imports = [$imports  ];
+
+  boot.initrd.kernelModules = [$initrdKernelModules ];
+  boot.kernelModules = [$kernelModules ];
+  boot.extraModulePackages = [$modulePackages ];
+
+  nix.maxJobs = $cpus;
+$attrs}
+EOF
+# workaround for a bug in substituteAll
diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh
new file mode 100644
index 00000000000..a4ac5b68dd7
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-install.sh
@@ -0,0 +1,238 @@
+#! @shell@
+
+# - [mount target device] <- currently disabled
+# - make Nix store etc.
+# - copy closure of Nix to target device
+# - register validity
+# - with a chroot to the target device:
+#   * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
+#   * run the activation script of the configuration (also installs Grub)
+
+# Parse the command line for the -I flag
+extraBuildFlags=()
+
+while [ "$#" -gt 0 ]; do
+    i="$1"; shift 1
+    case "$i" in
+      -I)
+        given_path="$1"; shift 1
+        absolute_path=$(readlink -m $given_path)
+        extraBuildFlags+=("$i" "/mnt$absolute_path")
+        ;;
+      *)
+        echo "$0: unknown option \`$i'"
+        exit 1
+        ;;
+    esac
+done
+
+set -e
+shopt -s nullglob
+
+if test -z "$mountPoint"; then
+    mountPoint=/mnt
+fi
+
+if test -z "$NIXOS_CONFIG"; then
+    NIXOS_CONFIG=/etc/nixos/configuration.nix
+fi
+
+if ! test -e "$mountPoint"; then
+    echo "mount point $mountPoint doesn't exist"
+    exit 1
+fi
+
+if ! grep -F -q " $mountPoint " /proc/mounts; then
+    echo "$mountPoint doesn't appear to be a mount point"
+    exit 1
+fi
+
+if ! test -e "$mountPoint/$NIXOS_CONFIG"; then
+    echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist"
+    exit 1
+fi
+
+
+
+# Mount some stuff in the target root directory.  We bind-mount /etc
+# into the chroot because we need networking and the nixbld user
+# accounts in /etc/passwd.  But we do need the target's /etc/nixos.
+mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/mnt $mountPoint/mnt2 $mountPoint/mnt-nixos $mountPoint/mnt-nixpkgs $mountPoint/etc /etc/nixos
+mount --make-private / # systemd makes / shared, which is annoying
+mount --bind / $mountPoint/mnt
+mount --bind /nix $mountPoint/mnt/nix
+mount --bind /nix/store $mountPoint/mnt/nix/store
+mount --bind /dev $mountPoint/dev
+mount --bind /dev/shm $mountPoint/dev/shm
+mount --bind /proc $mountPoint/proc
+mount --bind /sys $mountPoint/sys
+mount --bind /sys/firmware/efi/efivars $mountPoint/sys/firmware/efi/efivars &>/dev/null || true
+mount --bind $mountPoint/etc/nixos $mountPoint/mnt2
+mount --bind /etc $mountPoint/etc
+mount --bind $mountPoint/mnt2 $mountPoint/etc/nixos
+
+cleanup() {
+    set +e
+    mountpoint -q $mountPoint/etc/nixos && umount $mountPoint/etc/nixos
+    mountpoint -q $mountPoint/etc && umount $mountPoint/etc
+    umount $mountPoint/mnt2
+    umount $mountPoint/mnt-nixos
+    umount $mountPoint/mnt-nixpkgs
+    umount $mountPoint/sys/firmware/efi/efivars &>/dev/null || true
+    umount $mountPoint/sys
+    umount $mountPoint/proc
+    umount $mountPoint/dev/shm
+    umount $mountPoint/dev
+    umount $mountPoint/mnt/nix/store
+    umount $mountPoint/mnt/nix
+    umount $mountPoint/mnt
+    rmdir $mountPoint/mnt $mountPoint/mnt2 $mountPoint/mnt-nixos $mountPoint/mnt-nixpkgs
+}
+
+trap "cleanup" EXIT
+
+mkdir -m 01777 -p $mountPoint/tmp
+mkdir -m 0755 -p $mountPoint/var
+
+
+# Create the necessary Nix directories on the target device, if they
+# don't already exist.
+mkdir -m 0755 -p \
+    $mountPoint/nix/var/nix/gcroots \
+    $mountPoint/nix/var/nix/temproots \
+    $mountPoint/nix/var/nix/manifests \
+    $mountPoint/nix/var/nix/userpool \
+    $mountPoint/nix/var/nix/profiles \
+    $mountPoint/nix/var/nix/db \
+    $mountPoint/nix/var/log/nix/drvs
+
+mkdir -m 1775 -p $mountPoint/nix/store
+build_users_group=$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"build-users-group"};')
+if test -n "$build_users_group"; then
+    chown root:"$build_users_group" $mountPoint/nix/store
+else
+    chown root $mountPoint/nix/store
+fi
+
+
+# Get the store paths to copy from the references graph.
+storePaths=$(@perl@/bin/perl @pathsFromGraph@ @nixClosure@)
+
+
+# Copy Nix to the Nix store on the target device.
+echo "copying Nix to $mountPoint...."
+for i in $storePaths; do
+    echo "  $i"
+    chattr -R -i $mountPoint/$i 2> /dev/null || true # clear immutable bit
+    rsync -a $i $mountPoint/nix/store/
+done
+
+
+# We don't have locale-archive in the chroot, so clear $LANG.
+export LANG=
+export LC_ALL=
+export LC_TIME=
+
+
+# There is no daemon in the chroot
+unset NIX_REMOTE
+
+
+# Create a temporary Nix config file that causes the nixbld users to
+# be used.
+if test -n "$build_users_group"; then
+    echo "build-users-group = $build_users_group" > $mountPoint/tmp/nix.conf
+fi
+binary_caches=$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"binary-caches"};')
+if test -n "$binary_caches"; then
+    echo "binary-caches = $binary_caches" >> $mountPoint/tmp/nix.conf
+fi
+export NIX_CONF_DIR=/tmp
+
+
+# Register the paths in the Nix closure as valid.  This is necessary
+# to prevent them from being deleted the first time we install
+# something.  (I.e., Nix will see that, e.g., the glibc path is not
+# valid, delete it to get it out of the way, but as a result nothing
+# will work anymore.)
+chroot $mountPoint @nix@/bin/nix-store --register-validity < @nixClosure@
+
+
+# Create the required /bin/sh symlink; otherwise lots of things
+# (notably the system() function) won't work.
+mkdir -m 0755 -p $mountPoint/bin
+# !!! assuming that @shell@ is in the closure
+ln -sf @shell@ $mountPoint/bin/sh
+
+
+if test -n "$NIXOS_PREPARE_CHROOT_ONLY"; then
+    echo "User requested only to prepare chroot. Exiting."
+    exit 0
+fi
+
+
+# Make the build below copy paths from the CD if possible.  Note that
+# /mnt in the chroot is the root of the CD.
+export NIX_OTHER_STORES=/mnt/nix:$NIX_OTHER_STORES
+
+p=@nix@/libexec/nix/substituters
+export NIX_SUBSTITUTERS=$p/copy-from-other-stores.pl:$p/download-from-binary-cache.pl
+
+
+# Make manifests available in the chroot.
+rm -f $mountPoint/nix/var/nix/manifests/*
+for i in /nix/var/nix/manifests/*.nixmanifest; do
+    chroot $mountPoint @nix@/bin/nix-store -r "$(readlink -f "$i")" > /dev/null
+    cp -pd "$i" $mountPoint/nix/var/nix/manifests/
+done
+
+
+# Get the absolute path to the NixOS/Nixpkgs sources.
+mount --bind $(readlink -f $(nix-instantiate --find-file nixpkgs)) $mountPoint/mnt-nixpkgs
+mount --bind $(readlink -f $(nix-instantiate --find-file nixos)) $mountPoint/mnt-nixos
+
+
+# Build the specified Nix expression in the target store and install
+# it into the system configuration profile.
+echo "building the system configuration..."
+NIX_PATH="nixpkgs=/mnt-nixpkgs:nixos=/mnt-nixos:nixos-config=$NIXOS_CONFIG" NIXOS_CONFIG= \
+    chroot $mountPoint @nix@/bin/nix-env \
+    "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system -f '<nixos>' --set -A system --show-trace
+
+
+# Copy the NixOS/Nixpkgs sources to the target as the initial contents
+# of the NixOS channel.
+mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles
+mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user
+mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root
+srcs=$(nix-env "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "")
+if test -n "$srcs"; then
+    echo "copying NixOS/Nixpkgs sources..."
+    chroot $mountPoint @nix@/bin/nix-env \
+        "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -i "$srcs" --quiet
+fi
+mkdir -m 0700 -p $mountPoint/root/.nix-defexpr
+ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels
+
+
+# We're done building/downloading, so we don't need the /etc bind
+# mount anymore.  In fact, below we want to modify the target's /etc.
+umount $mountPoint/etc/nixos
+umount $mountPoint/etc
+
+
+# Grub needs an mtab.
+ln -sfn /proc/mounts $mountPoint/etc/mtab
+
+
+# Mark the target as a NixOS installation, otherwise
+# switch-to-configuration will chicken out.
+touch $mountPoint/etc/NIXOS
+
+
+# Switch to the new system configuration.  This will install Grub with
+# a menu default pointing at the kernel/initrd/etc of the new
+# configuration.
+echo "finalising the installation..."
+NIXOS_INSTALL_GRUB=1 chroot $mountPoint \
+    /nix/var/nix/profiles/system/bin/switch-to-configuration boot
diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh
new file mode 100644
index 00000000000..7f008d62c24
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-option.sh
@@ -0,0 +1,395 @@
+#! @shell@ -e
+
+# Allow the location of NixOS sources and the system configuration
+# file to be overridden.
+
+: ${mountPoint=/mnt}
+: ${NIXOS_CONFIG=/etc/nixos/configuration.nix}
+export NIXOS_CONFIG
+
+usage () {
+  echo 1>&2 "
+Usage: $0 [-v] [-d] [-l] [--xml] OPTION_NAME
+       $0 --install
+
+This program allows you to inspect the current value of NixOS
+configuration options.  It can also generate a basic NixOS
+configuration file.
+
+Options:
+
+  -i | --install        Write a template NixOS configuration file to
+                        ${mountPoint:+$mountPoint/}$NIXOS_CONFIG.
+  -v | --value          Display the current value, based on your
+                        configuration.
+  -d | --description    Display the default value, the example and the
+                        description.
+  -l | --lookup         Display where the option is defined and where it
+                        is declared.
+  --xml                 Print an XML representation of the result.
+                        Implies -vdl options.
+  --help                Show this message.
+
+Environment variables affecting $0:
+
+  \$mountPoint          Path to the target file system.
+  \$NIXOS_CONFIG        Path to your configuration file.
+
+"
+
+  exit 1;
+}
+
+#####################
+# Process Arguments #
+#####################
+
+desc=false
+defs=false
+value=false
+xml=false
+install=false
+verbose=false
+
+option=""
+
+argfun=""
+for arg; do
+  if test -z "$argfun"; then
+    case $arg in
+      -*)
+        longarg=""
+        sarg="$arg"
+        while test "$sarg" != "-"; do
+          case $sarg in
+            --*) longarg=$arg; sarg="--";;
+            -d*) longarg="$longarg --description";;
+            -v*) longarg="$longarg --value";;
+            -l*) longarg="$longarg --lookup";;
+            -i*) longarg="$longarg --install";;
+            -*) usage;;
+          esac
+          # remove the first letter option
+          sarg="-${sarg#??}"
+        done
+        ;;
+      *) longarg=$arg;;
+    esac
+    for larg in $longarg; do
+      case $larg in
+        --description) desc=true;;
+        --value) value=true;;
+        --lookup) defs=true;;
+        --xml) xml=true;;
+        --install) install=true;;
+        --verbose) verbose=true;;
+        --help) usage;;
+        -*) usage;;
+        *) if test -z "$option"; then
+             option="$larg"
+           else
+             usage
+           fi;;
+      esac
+    done
+  else
+    case $argfun in
+      set_*)
+        var=$(echo $argfun | sed 's,^set_,,')
+        eval $var=$arg
+        ;;
+    esac
+    argfun=""
+  fi
+done
+
+if $xml; then
+  value=true
+  desc=true
+  defs=true
+fi
+
+# --install cannot be used with -d -v -l without option name.
+if $value || $desc || $defs && $install && test -z "$option"; then
+  usage
+fi
+
+generate=false
+if ! $defs && ! $desc && ! $value && $install && test -z "$option"; then
+  generate=true
+fi
+
+if ! $defs && ! $desc; then
+  value=true
+fi
+
+if $verbose; then
+  set -x
+else
+  set +x
+fi
+
+#############################
+# Process the configuration #
+#############################
+
+evalNix(){
+  nix-instantiate - --eval-only "$@"
+}
+
+evalAttr(){
+  local prefix=$1
+  local suffix=$2
+  local strict=$3
+  echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" |
+    evalNix ${strict:+--strict}
+}
+
+evalOpt(){
+  evalAttr "eval.options" "$@"
+}
+
+evalCfg(){
+  evalAttr "config" "$@"
+}
+
+findSources(){
+  local suffix=$1
+  echo "builtins.map (f: f.source) (import <nixos> {}).eval.options${option:+.$option}.$suffix" |
+    evalNix --strict
+}
+
+# Given a result from nix-instantiate, recover the list of attributes it
+# contains.
+attrNames() {
+  local attributeset=$1
+  # sed is used to replace un-printable subset by 0s, and to remove most of
+  # the inner-attribute set, which reduce the likelyhood to encounter badly
+  # pre-processed input.
+  echo "builtins.attrNames $attributeset" | \
+    sed 's,<[A-Z]*>,0,g; :inner; s/{[^\{\}]*};/0;/g; t inner;' | \
+    evalNix --strict
+}
+
+# map a simple list which contains strings or paths.
+nixMap() {
+  local fun="$1"
+  local list="$2"
+  local elem
+  for elem in $list; do
+    test $elem = '[' -o $elem = ']' && continue;
+    $fun $elem
+  done
+}
+
+if $install; then
+  NIXOS_CONFIG="$mountPoint$NIXOS_CONFIG"
+fi
+
+if $generate; then
+  mkdir -p $(dirname "$NIXOS_CONFIG")
+
+  # Scan the hardware and add the result to /etc/nixos/hardware-scan.nix.
+  hardware_config="${NIXOS_CONFIG%/configuration.nix}/hardware-configuration.nix"
+  if test -e "$hardware_config"; then
+    echo "A hardware configuration file exists, generation skipped."
+  else
+    echo "Generating a hardware configuration file in $hardware_config..."
+    nixos-hardware-scan > "$hardware_config"
+  fi
+
+  if test -e "$NIXOS_CONFIG"; then
+    echo 1>&2 "error: Cannot generate a template configuration because a configuration file exists."
+    exit 1
+  fi
+
+  nl="
+"
+  if test -e /sys/firmware/efi/efivars; then
+    l1="  # Use the gummiboot efi boot loader."
+    l2="  boot.loader.grub.enable = false;"
+    l3="  boot.loader.gummiboot.enable = true;"
+    l4="  boot.loader.efi.canTouchEfiVariables = true;"
+    # !!! Remove me when nixos is on 3.10 or greater by default
+    l5="  # EFI booting requires kernel >= 3.10"
+    l6="  boot.kernelPackages = pkgs.linuxPackages_3_10;"
+    bootloader_config="$l1$nl$l2$nl$l3$nl$l4$nl$nl$l5$nl$l6"
+  else
+    l1="  # Use the Grub2 boot loader."
+    l2="  boot.loader.grub.enable = true;"
+    l3="  boot.loader.grub.version = 2;"
+    l4="  # Define on which hard drive you want to install Grub."
+    l5='  # boot.loader.grub.device = "/dev/sda";'
+    bootloader_config="$l1$nl$l2$nl$l3$nl$nl$l4$nl$l5"
+  fi
+
+  echo "Generating a basic configuration file in $NIXOS_CONFIG..."
+
+  # Generate a template configuration file where the user has to
+  # fill the gaps.
+  cat <<EOF > "$NIXOS_CONFIG"
+# Edit this configuration file to define what should be installed on
+# the system.  Help is available in the configuration.nix(5) man page
+# or the NixOS manual available on virtual console 8 (Alt+F8).
+
+{ config, pkgs, ... }:
+
+{
+  imports =
+    [ # Include the results of the hardware scan.
+      ./hardware-configuration.nix
+    ];
+
+  boot.initrd.kernelModules =
+    [ # Specify all kernel modules that are necessary for mounting the root
+      # filesystem.
+      # "xfs" "ata_piix"
+      # fbcon # Uncomment this when EFI booting to see the console before the root partition is mounted
+    ];
+    
+$bootloader_config
+
+  # networking.hostName = "nixos"; # Define your hostname.
+  # networking.wireless.enable = true;  # Enables Wireless.
+
+  # Add filesystem entries for each partition that you want to see
+  # mounted at boot time.  This should include at least the root
+  # filesystem.
+
+  # fileSystems."/".device = "/dev/disk/by-label/nixos";
+
+  # fileSystems."/data" =     # where you want to mount the device
+  #   { device = "/dev/sdb";  # the device
+  #     fsType = "ext3";      # the type of the partition
+  #     options = "data=journal";
+  #   };
+
+  # List swap partitions activated at boot time.
+  swapDevices =
+    [ # { device = "/dev/disk/by-label/swap"; }
+    ];
+
+  # Select internationalisation properties.
+  # i18n = {
+  #   consoleFont = "lat9w-16";
+  #   consoleKeyMap = "us";
+  #   defaultLocale = "en_US.UTF-8";
+  # };
+
+  # List services that you want to enable:
+
+  # Enable the OpenSSH daemon.
+  # services.openssh.enable = true;
+
+  # Enable CUPS to print documents.
+  # services.printing.enable = true;
+
+  # Enable the X11 windowing system.
+  # services.xserver.enable = true;
+  # services.xserver.layout = "us";
+  # services.xserver.xkbOptions = "eurosign:e";
+
+  # Enable the KDE Desktop Environment.
+  # services.xserver.displayManager.kdm.enable = true;
+  # services.xserver.desktopManager.kde4.enable = true;
+}
+EOF
+
+  exit 0
+fi;
+
+# This duplicates the work made below, but it is useful for processing
+# the output of nixos-option with other tools such as nixos-gui.
+if $xml; then
+  evalNix --xml --no-location <<EOF
+let
+  reach = attrs: attrs${option:+.$option};
+  nixos = import <nixos> {};
+  nixpkgs = import <nixpkgs> {};
+  sources = builtins.map (f: f.source);
+  opt = reach nixos.eval.options;
+  cfg = reach nixos.config;
+in
+
+with nixpkgs.lib;
+
+let
+  optStrict = v:
+    let
+      traverse = x :
+        if isAttrs x then
+          if x ? outPath then true
+          else all id (mapAttrsFlatten (n: traverseNoAttrs) x)
+        else traverseNoAttrs x;
+      traverseNoAttrs = x:
+        # do not continue in attribute sets
+        if isAttrs x then true
+        else if isList x then all id (map traverse x)
+        else true;
+    in assert traverse v; v;
+in
+
+if isOption opt then
+  optStrict ({}
+  // optionalAttrs (opt ? default) { inherit (opt) default; }
+  // optionalAttrs (opt ? example) { inherit (opt) example; }
+  // optionalAttrs (opt ? description) { inherit (opt) description; }
+  // optionalAttrs (opt ? type) { typename = opt.type.name; }
+  // optionalAttrs (opt ? options) { inherit (opt) options; }
+  // {
+    # to disambiguate the xml output.
+    _isOption = true;
+    declarations = sources opt.declarations;
+    definitions = sources opt.definitions;
+    value = cfg;
+  })
+else
+  opt
+EOF
+  exit $?
+fi
+
+if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then
+  $value && evalCfg;
+
+  if $desc; then
+    $value && echo;
+
+    if default=$(evalOpt "default" - 2> /dev/null); then
+      echo "Default: $default"
+    else
+      echo "Default: <None>"
+    fi
+    if example=$(evalOpt "example" - 2> /dev/null); then
+      echo "Example: $example"
+    fi
+    echo "Description:"
+    eval printf $(evalOpt "description")
+  fi
+
+  if $defs; then
+    $desc || $value && echo;
+
+    printPath () { echo "  $1"; }
+
+    echo "Declared by:"
+    nixMap printPath "$(findSources "declarations")"
+    echo ""
+    echo "Defined by:"
+    nixMap printPath "$(findSources "definitions")"
+    echo ""
+  fi
+
+else
+  # echo 1>&2 "Warning: This value is not an option."
+
+  result=$(evalCfg)
+  if names=$(attrNames "$result" 2> /dev/null); then
+    echo 1>&2 "This attribute set contains:"
+    escapeQuotes () { eval echo "$1"; }
+    nixMap escapeQuotes "$names"
+  else
+    echo 1>&2 "An error occured while looking for attribute names."
+    echo $result
+  fi
+fi
diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh
new file mode 100644
index 00000000000..8734cb273d4
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-rebuild.sh
@@ -0,0 +1,222 @@
+#! @shell@ -e
+
+showSyntax() {
+    # !!! more or less cut&paste from
+    # system/switch-to-configuration.sh (which we call, of course).
+    cat <<EOF
+Usage: $0 [OPTIONS...] OPERATION
+
+The operation is one of the following:
+
+  switch:   make the configuration the boot default and activate now
+  boot:     make the configuration the boot default
+  test:     activate the configuration, but don't make it the boot default
+  build:    build the configuration, but don't make it the default or
+            activate it
+  build-vm: build a virtual machine containing the configuration
+            (useful for testing)
+  build-vm-with-bootloader:
+            like build-vm, but include a boot loader in the VM
+  dry-run:  just show what store paths would be built/downloaded
+
+Options:
+
+  --upgrade              fetch the latest version of NixOS before rebuilding
+  --install-grub         (re-)install the Grub bootloader
+  --no-build-nix         don't build the latest Nix from Nixpkgs before
+                           building NixOS
+  --rollback             restore the previous NixOS configuration (only
+                           with switch, boot, test, build)
+  --profile-name / -p    install in the specified system profile
+  --fast                 same as --no-build-nix --show-trace
+
+Various nix-build options are also accepted, in particular:
+
+  --show-trace           show a detailed stack trace for evaluation errors
+
+Environment variables affecting nixos-rebuild:
+
+  \$NIX_PATH              Nix expression search path
+  \$NIXOS_CONFIG          path to the NixOS system configuration specification
+EOF
+    exit 1
+}
+
+
+# Parse the command line.
+extraBuildFlags=()
+action=
+buildNix=1
+rollback=
+upgrade=
+repair=
+profile=/nix/var/nix/profiles/system
+
+while [ "$#" -gt 0 ]; do
+    i="$1"; shift 1
+    case "$i" in
+      --help)
+        showSyntax
+        ;;
+      switch|boot|test|build|dry-run|build-vm|build-vm-with-bootloader)
+        action="$i"
+        ;;
+      --install-grub)
+        export NIXOS_INSTALL_GRUB=1
+        ;;
+      --no-build-nix)
+        buildNix=
+        ;;
+      --rollback)
+        rollback=1
+        ;;
+      --upgrade)
+        upgrade=1
+        ;;
+      --repair)
+        repair=1
+        extraBuildFlags+=("$i")
+        ;;
+      --show-trace|--no-build-hook|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair)
+        extraBuildFlags+=("$i")
+        ;;
+      --max-jobs|-j|--cores|-I)
+        j="$1"; shift 1
+        extraBuildFlags+=("$i" "$j")
+        ;;
+      --option)
+        j="$1"; shift 1
+        k="$1"; shift 1
+        extraBuildFlags+=("$i" "$j" "$k")
+        ;;
+      --fast)
+        buildNix=
+        extraBuildFlags+=(--show-trace)
+        ;;
+      --profile-name|-p)
+        if [ -z "$1" ]; then
+            echo "$0: ‘--profile-name’ requires an argument"
+            exit 1
+        fi
+        if [ "$1" != system ]; then
+            profile="/nix/var/nix/profiles/system-profiles/$1"
+            mkdir -p -m 0755 "$(dirname "$profile")"
+        fi
+        shift 1
+        ;;
+      *)
+        echo "$0: unknown option \`$i'"
+        exit 1
+        ;;
+    esac
+done
+
+if [ -z "$action" ]; then showSyntax; fi
+
+if [ -n "$rollback" ]; then
+    buildNix=
+fi
+
+
+tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX)
+trap 'rm -rf "$tmpDir"' EXIT
+
+
+# If the Nix daemon is running, then use it.  This allows us to use
+# the latest Nix from Nixpkgs (below) for expression evaluation, while
+# still using the old Nix (via the daemon) for actual store access.
+# This matters if the new Nix in Nixpkgs has a schema change.  It
+# would upgrade the schema, which should only happen once we actually
+# switch to the new configuration.
+# If --repair is given, don't try to use the Nix daemon, because the
+# flag can only be used directly.
+if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then
+    export NIX_REMOTE=${NIX_REMOTE:-daemon}
+fi
+
+
+# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’.
+if [ -n "$upgrade" ]; then
+    nix-channel --update nixos
+fi
+
+
+# First build Nix, since NixOS may require a newer version than the
+# current one.  Of course, the same goes for Nixpkgs, but Nixpkgs is
+# more conservative.
+if [ "$action" != dry-run -a -n "$buildNix" ]; then
+    echo "building Nix..." >&2
+    if ! nix-build '<nixos>' -A config.environment.nix -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
+        if ! nix-build '<nixos>' -A nixFallback -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then
+            nix-build '<nixpkgs>' -A nixUnstable -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null
+        fi
+    fi
+    PATH=$tmpDir/nix/bin:$PATH
+fi
+
+
+# Update the version suffix if we're building from Git (so that
+# nixos-version shows something useful).
+if nixos=$(nix-instantiate --find-file nixos "${extraBuildFlags[@]}"); then
+    suffix=$(@shell@ $nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}")
+    if [ -n "$suffix" ]; then
+        echo -n "$suffix" > "$nixos/.version-suffix" || true
+    fi
+fi
+
+
+if [ "$action" = dry-run ]; then
+    extraBuildFlags+=(--dry-run)
+fi
+
+
+# Either upgrade the configuration in the system profile (for "switch"
+# or "boot"), or just build it and create a symlink "result" in the
+# current directory (for "build" and "test").
+if [ -z "$rollback" ]; then
+    echo "building the system configuration..." >&2
+    if [ "$action" = switch -o "$action" = boot ]; then
+        nix-env "${extraBuildFlags[@]}" -p "$profile" -f '<nixos>' --set -A system
+        pathToConfig="$profile"
+    elif [ "$action" = test -o "$action" = build -o "$action" = dry-run ]; then
+        nix-build '<nixos>' -A system -K -k "${extraBuildFlags[@]}" > /dev/null
+        pathToConfig=./result
+    elif [ "$action" = build-vm ]; then
+        nix-build '<nixos>' -A vm -K -k "${extraBuildFlags[@]}" > /dev/null
+        pathToConfig=./result
+    elif [ "$action" = build-vm-with-bootloader ]; then
+        nix-build '<nixos>' -A vmWithBootLoader -K -k "${extraBuildFlags[@]}" > /dev/null
+        pathToConfig=./result
+    else
+        showSyntax
+    fi
+else # [ -n "$rollback" ]
+    if [ "$action" = switch -o "$action" = boot ]; then
+        nix-env --rollback -p "$profile"
+        pathToConfig="$profile"
+    elif [ "$action" = test -o "$action" = build ]; then
+        systemNumber=$(
+            nix-env -p "$profile" --list-generations |
+            sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h'
+        )
+        ln -sT "$profile"-${systemNumber}-link ./result
+        pathToConfig=./result
+    else
+        showSyntax
+    fi
+fi
+
+
+# If we're not just building, then make the new configuration the boot
+# default and/or activate it now.
+if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then
+    $pathToConfig/bin/switch-to-configuration "$action"
+fi
+
+
+if [ "$action" = build-vm ]; then
+    cat >&2 <<EOF
+
+Done.  The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm).
+EOF
+fi
diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh
new file mode 100644
index 00000000000..5dbf277fe4c
--- /dev/null
+++ b/nixos/modules/installer/tools/nixos-version.sh
@@ -0,0 +1,2 @@
+#! @shell@
+echo "@nixosVersion@ (@nixosCodeName@)"
diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix
new file mode 100644
index 00000000000..c761d74a890
--- /dev/null
+++ b/nixos/modules/installer/tools/tools.nix
@@ -0,0 +1,112 @@
+# This module generates nixos-install, nixos-rebuild,
+# nixos-hardware-scan, etc.
+
+{ config, pkgs, modulesPath, ... }:
+
+let
+  ### implementation
+  cfg = config.installer;
+
+  makeProg = args: pkgs.substituteAll (args // {
+    dir = "bin";
+    isExecutable = true;
+  });
+
+  nixosBuildVMS = makeProg {
+    name = "nixos-build-vms";
+    src = ./nixos-build-vms/nixos-build-vms.sh;
+  };
+
+  nixosInstall = makeProg {
+    name = "nixos-install";
+    src = ./nixos-install.sh;
+
+    inherit (pkgs) perl pathsFromGraph;
+    nix = config.environment.nix;
+
+    nixClosure = pkgs.runCommand "closure"
+      { exportReferencesGraph = ["refs" config.environment.nix]; }
+      "cp refs $out";
+  };
+
+  nixosRebuild = makeProg {
+    name = "nixos-rebuild";
+    src = ./nixos-rebuild.sh;
+  };
+
+  /*
+  nixosGenSeccureKeys = makeProg {
+    name = "nixos-gen-seccure-keys";
+    src = ./nixos-gen-seccure-keys.sh;
+  };
+  */
+
+  nixosHardwareScan = makeProg {
+    name = "nixos-hardware-scan";
+    src = ./nixos-hardware-scan.pl;
+    inherit (pkgs) perl dmidecode;
+  };
+
+  nixosOption = makeProg {
+    name = "nixos-option";
+    src = ./nixos-option.sh;
+  };
+
+  nixosVersion = makeProg {
+    name = "nixos-version";
+    src = ./nixos-version.sh;
+    inherit (config.system) nixosVersion nixosCodeName;
+  };
+
+  nixosGui = pkgs.xulrunnerWrapper {
+    launcher = "nixos-gui";
+    application = pkgs.stdenv.mkDerivation {
+      name = "nixos-gui";
+      buildCommand = ''
+        cp -r "$gui" "$out"
+
+        # Do not force the copy if the file exists in the sources (this
+        # happens for developpers)
+        test -e "$out/chrome/content/jquery-1.5.2.js" ||
+          cp -f "$jquery" "$out/chrome/content/jquery-1.5.2.js"
+      '';
+      gui = pkgs.lib.cleanSource "${modulesPath}/../gui";
+      jquery = pkgs.fetchurl {
+        url = http://code.jquery.com/jquery-1.5.2.min.js;
+        sha256 = "8f0a19ee8c606b35a10904951e0a27da1896eafe33c6e88cb7bcbe455f05a24a";
+      };
+    };
+  };
+
+in
+
+{
+  options = {
+
+    installer.enableGraphicalTools = pkgs.lib.mkOption {
+      default = false;
+      type = with pkgs.lib.types; bool;
+      example = true;
+      description = ''
+        Enable the installation of graphical tools.
+      '';
+    };
+
+  };
+
+  config = {
+    environment.systemPackages =
+      [ nixosBuildVMS
+        nixosInstall
+        nixosRebuild
+        nixosHardwareScan
+        #nixosGenSeccureKeys
+        nixosOption
+        nixosVersion
+      ] ++ pkgs.lib.optional cfg.enableGraphicalTools nixosGui;
+
+    system.build = {
+      inherit nixosInstall nixosHardwareScan nixosOption;
+    };
+  };
+}
diff --git a/nixos/modules/installer/virtualbox-demo.nix b/nixos/modules/installer/virtualbox-demo.nix
new file mode 100644
index 00000000000..76cc29a1fac
--- /dev/null
+++ b/nixos/modules/installer/virtualbox-demo.nix
@@ -0,0 +1,19 @@
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+{
+  imports =
+    [ ../virtualisation/virtualbox-image.nix
+      ../installer/cd-dvd/channel.nix
+      ../profiles/demo.nix
+      ../profiles/clone-config.nix
+    ];
+
+  # Allow mounting of shared folders.
+  users.extraUsers.demo.extraGroups = [ "vboxsf" ];
+
+  # Add some more video drivers to give X11 a shot at working in
+  # VMware and QEMU.
+  services.xserver.videoDrivers = mkOverride 40 [ "virtualbox" "vmware" "cirrus" "vesa" ];
+}