2009-06-05 14:35:27 +01:00
|
|
|
# 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.
|
|
|
|
|
2014-04-14 15:26:48 +01:00
|
|
|
{ config, lib, pkgs, ... }:
|
2009-11-14 16:12:02 +00:00
|
|
|
|
2014-04-14 15:26:48 +01:00
|
|
|
with lib;
|
2009-06-05 14:35:27 +01:00
|
|
|
|
|
|
|
let
|
2009-06-09 13:01:31 +01:00
|
|
|
|
2014-10-26 20:29:04 +00:00
|
|
|
# The configuration file for syslinux.
|
|
|
|
isolinuxCfg =
|
2013-09-04 12:05:09 +01:00
|
|
|
''
|
2014-10-26 20:29:04 +00:00
|
|
|
SERIAL 0 38400
|
|
|
|
UI vesamenu.c32
|
|
|
|
MENU TITLE NixOS
|
|
|
|
MENU BACKGROUND /isolinux/background.png
|
|
|
|
|
|
|
|
LABEL boot
|
|
|
|
MENU LABEL Boot NixOS
|
|
|
|
LINUX /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
|
|
|
INITRD /boot/initrd
|
|
|
|
|
|
|
|
LABEL chain
|
|
|
|
MENU LABEL Boot existing OS
|
|
|
|
COM32 chain.c32
|
|
|
|
APPEND hd0 0
|
|
|
|
|
|
|
|
LABEL reboot
|
|
|
|
MENU LABEL Reboot
|
|
|
|
COM32 reboot.c32
|
|
|
|
|
|
|
|
LABEL poweroff
|
|
|
|
MENU LABEL Power Off
|
|
|
|
COM32 poweroff.c32
|
2013-09-04 12:05:09 +01:00
|
|
|
'';
|
|
|
|
|
|
|
|
# The efi boot image
|
2013-11-14 23:18:27 +00:00
|
|
|
efiDir = pkgs.runCommand "efi-directory" {} ''
|
2014-10-26 20:29:04 +00:00
|
|
|
mkdir -p $out/EFI/boot
|
|
|
|
cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi
|
2013-11-14 23:18:27 +00:00
|
|
|
mkdir -p $out/loader/entries
|
|
|
|
echo "title NixOS LiveCD" > $out/loader/entries/nixos-livecd.conf
|
|
|
|
echo "linux /boot/bzImage" >> $out/loader/entries/nixos-livecd.conf
|
|
|
|
echo "initrd /boot/initrd" >> $out/loader/entries/nixos-livecd.conf
|
|
|
|
echo "options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" >> $out/loader/entries/nixos-livecd.conf
|
|
|
|
echo "default nixos-livecd" > $out/loader/loader.conf
|
|
|
|
echo "timeout 5" >> $out/loader/loader.conf
|
|
|
|
'';
|
|
|
|
|
2013-10-09 16:44:50 +01:00
|
|
|
efiImg = pkgs.runCommand "efi-image_eltorito" { buildInputs = [ pkgs.mtools ]; }
|
2013-09-04 12:05:09 +01:00
|
|
|
''
|
|
|
|
#Let's hope 10M is enough
|
|
|
|
dd bs=2048 count=5120 if=/dev/zero of="$out"
|
|
|
|
${pkgs.dosfstools}/sbin/mkfs.vfat "$out"
|
2013-11-14 23:18:27 +00:00
|
|
|
mcopy -svi "$out" ${efiDir}/* ::
|
|
|
|
mmd -i "$out" boot
|
2013-10-09 16:44:50 +01:00
|
|
|
mcopy -v -i "$out" \
|
2013-11-14 23:18:27 +00:00
|
|
|
${config.boot.kernelPackages.kernel}/bzImage ::boot/bzImage
|
2013-10-09 16:44:50 +01:00
|
|
|
mcopy -v -i "$out" \
|
2013-11-14 23:18:27 +00:00
|
|
|
${config.system.build.initialRamdisk}/initrd ::boot/initrd
|
2014-05-21 13:06:31 +01:00
|
|
|
''; # */
|
2013-09-04 12:05:09 +01:00
|
|
|
|
|
|
|
targetArch = if pkgs.stdenv.isi686 then
|
|
|
|
"ia32"
|
|
|
|
else if pkgs.stdenv.isx86_64 then
|
|
|
|
"x64"
|
|
|
|
else
|
|
|
|
throw "Unsupported architecture";
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
{
|
2009-06-09 13:01:31 +01:00
|
|
|
options = {
|
|
|
|
|
2009-11-14 16:12:02 +00:00
|
|
|
isoImage.isoName = mkOption {
|
2011-04-20 11:48:52 +01:00
|
|
|
default = "${config.isoImage.isoName}.iso";
|
2009-06-09 16:23:03 +01:00
|
|
|
description = ''
|
|
|
|
Name of the generated ISO image file.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2011-04-20 11:48:52 +01:00
|
|
|
isoImage.isoBaseName = mkOption {
|
|
|
|
default = "nixos";
|
|
|
|
description = ''
|
|
|
|
Prefix of the name of the generated ISO image file.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-14 16:12:02 +00:00
|
|
|
isoImage.compressImage = mkOption {
|
2009-06-09 16:23:03 +01:00
|
|
|
default = false;
|
|
|
|
description = ''
|
|
|
|
Whether the ISO image should be compressed using
|
|
|
|
<command>bzip2</command>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-14 16:12:02 +00:00
|
|
|
isoImage.volumeID = mkOption {
|
2009-06-09 16:23:03 +01:00
|
|
|
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.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-14 16:12:02 +00:00
|
|
|
isoImage.contents = mkOption {
|
2014-08-27 22:41:15 +01:00
|
|
|
example = literalExample ''
|
2009-06-09 13:01:31 +01:00
|
|
|
[ { source = pkgs.memtest86 + "/memtest.bin";
|
|
|
|
target = "boot/memtest.bin";
|
|
|
|
}
|
2014-08-27 22:41:15 +01:00
|
|
|
]
|
|
|
|
'';
|
2009-06-09 13:01:31 +01:00
|
|
|
description = ''
|
2009-06-09 14:27:50 +01:00
|
|
|
This option lists files to be copied to fixed locations in the
|
|
|
|
generated ISO image.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2009-11-14 16:12:02 +00:00
|
|
|
isoImage.storeContents = mkOption {
|
2014-08-27 22:41:15 +01:00
|
|
|
example = literalExample "[ pkgs.stdenv ]";
|
2009-06-09 14:27:50 +01:00
|
|
|
description = ''
|
|
|
|
This option lists additional derivations to be included in the
|
|
|
|
Nix store in the generated ISO image.
|
2009-06-09 13:01:31 +01:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2010-08-29 13:11:31 +01:00
|
|
|
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.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2012-03-16 05:37:24 +00:00
|
|
|
isoImage.makeEfiBootable = mkOption {
|
|
|
|
default = false;
|
|
|
|
description = ''
|
2012-03-16 11:31:33 +00:00
|
|
|
Whether the ISO image should be an efi-bootable volume.
|
2012-03-16 05:37:24 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2014-10-26 20:29:04 +00:00
|
|
|
isoImage.makeUsbBootable = mkOption {
|
|
|
|
default = false;
|
|
|
|
description = ''
|
|
|
|
Whether the ISO image should be bootable from CD as well as USB.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
isoImage.splashImage = mkOption {
|
|
|
|
default = pkgs.fetchurl {
|
|
|
|
url = https://raw.githubusercontent.com/NixOS/nixos-artwork/5729ab16c6a5793c10a2913b5a1b3f59b91c36ee/ideas/grub-splash/grub-nixos-1.png;
|
|
|
|
sha256 = "43fd8ad5decf6c23c87e9026170a13588c2eba249d9013cb9f888da5e2002217";
|
|
|
|
};
|
|
|
|
description = ''
|
|
|
|
The splash image to use in the bootloader.
|
|
|
|
'';
|
|
|
|
};
|
2012-03-16 05:37:24 +00:00
|
|
|
|
2009-06-09 13:01:31 +01:00
|
|
|
};
|
|
|
|
|
2009-06-05 14:35:27 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
config = {
|
2009-11-10 21:42:38 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
boot.loader.grub.version = 2;
|
2009-11-10 21:42:38 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# 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;
|
2009-11-13 16:45:41 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# !!! Hack - attributes expected by other modules.
|
|
|
|
system.boot.loader.kernelFile = "bzImage";
|
2014-10-26 20:29:04 +00:00
|
|
|
environment.systemPackages = [ pkgs.grub2 pkgs.syslinux ];
|
2009-11-13 16:45:41 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# 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}" ];
|
2011-09-14 19:20:50 +01:00
|
|
|
|
2014-05-21 13:06:31 +01:00
|
|
|
fileSystems."/" =
|
|
|
|
{ fsType = "tmpfs";
|
|
|
|
options = "mode=0755";
|
|
|
|
};
|
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# Note that /dev/root is a symlink to the actual root device
|
2014-05-21 13:06:31 +01:00
|
|
|
# specified on the kernel command line, created in the stage 1
|
|
|
|
# init script.
|
|
|
|
fileSystems."/iso" =
|
|
|
|
{ device = "/dev/root";
|
|
|
|
neededForBoot = true;
|
|
|
|
noCheck = true;
|
|
|
|
};
|
2009-11-13 16:45:41 +00:00
|
|
|
|
2014-07-30 14:44:47 +01:00
|
|
|
# In stage 1, mount a tmpfs on top of /nix/store (the squashfs
|
|
|
|
# image) to make this a live CD.
|
2014-05-21 13:06:31 +01:00
|
|
|
fileSystems."/nix/.ro-store" =
|
2013-09-04 12:05:09 +01:00
|
|
|
{ fsType = "squashfs";
|
2014-05-21 13:06:31 +01:00
|
|
|
device = "/iso/nix-store.squashfs";
|
2013-09-04 12:05:09 +01:00
|
|
|
options = "loop";
|
2014-05-21 13:06:31 +01:00
|
|
|
neededForBoot = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
fileSystems."/nix/.rw-store" =
|
|
|
|
{ fsType = "tmpfs";
|
|
|
|
options = "mode=0755";
|
|
|
|
neededForBoot = true;
|
2013-09-04 12:05:09 +01:00
|
|
|
};
|
2011-09-14 19:20:50 +01:00
|
|
|
|
2014-07-30 14:44:47 +01:00
|
|
|
fileSystems."/nix/store" =
|
|
|
|
{ fsType = "unionfs-fuse";
|
|
|
|
device = "unionfs";
|
|
|
|
options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
|
|
|
|
};
|
|
|
|
|
2014-10-26 20:29:04 +00:00
|
|
|
boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" ];
|
2012-03-16 05:37:24 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
boot.initrd.kernelModules = [ "loop" ];
|
2012-03-16 05:37:24 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# 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;
|
|
|
|
};
|
2010-01-09 15:13:06 +00:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# Individual files to be included on the CD, outside of the Nix
|
|
|
|
# store on the CD.
|
|
|
|
isoImage.contents =
|
2014-10-26 20:29:04 +00:00
|
|
|
[ { source = pkgs.substituteAll {
|
|
|
|
name = "isolinux.cfg";
|
|
|
|
src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
|
2013-10-02 11:29:07 +01:00
|
|
|
bootRoot = "/boot";
|
|
|
|
};
|
2014-10-26 20:29:04 +00:00
|
|
|
target = "/isolinux/isolinux.cfg";
|
2013-09-04 12:05:09 +01:00
|
|
|
}
|
|
|
|
{ source = config.boot.kernelPackages.kernel + "/bzImage";
|
|
|
|
target = "/boot/bzImage";
|
|
|
|
}
|
|
|
|
{ source = config.system.build.initialRamdisk + "/initrd";
|
|
|
|
target = "/boot/initrd";
|
|
|
|
}
|
|
|
|
{ source = config.system.build.squashfsStore;
|
|
|
|
target = "/nix-store.squashfs";
|
|
|
|
}
|
2014-10-26 20:29:04 +00:00
|
|
|
{ source = "${pkgs.syslinux}/share/syslinux";
|
|
|
|
target = "/isolinux";
|
|
|
|
}
|
|
|
|
{ source = config.isoImage.splashImage;
|
|
|
|
target = "/isolinux/background.png";
|
|
|
|
}
|
2013-10-02 11:29:07 +01:00
|
|
|
] ++ optionals config.isoImage.makeEfiBootable [
|
2013-09-04 12:05:09 +01:00
|
|
|
{ source = efiImg;
|
|
|
|
target = "/boot/efi.img";
|
|
|
|
}
|
2014-10-26 20:29:04 +00:00
|
|
|
{ source = "${efiDir}/EFI";
|
|
|
|
target = "/EFI";
|
2013-11-14 23:18:27 +00:00
|
|
|
}
|
|
|
|
{ source = "${efiDir}/loader";
|
|
|
|
target = "/loader";
|
|
|
|
}
|
2014-10-26 20:29:04 +00:00
|
|
|
];
|
2009-06-05 14:35:27 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# Create the ISO image.
|
|
|
|
system.build.isoImage = import ../../../lib/make-iso9660-image.nix ({
|
2014-10-26 20:29:04 +00:00
|
|
|
inherit (pkgs) stdenv perl pathsFromGraph xorriso syslinux;
|
2009-06-10 17:29:48 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
inherit (config.isoImage) isoName compressImage volumeID contents;
|
2011-09-14 19:20:50 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
bootable = true;
|
2014-10-26 20:29:04 +00:00
|
|
|
bootImage = "/isolinux/isolinux.bin";
|
|
|
|
} // optionalAttrs config.isoImage.makeUsbBootable {
|
|
|
|
usbBootable = true;
|
|
|
|
isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
|
2013-10-02 11:29:07 +01:00
|
|
|
} // optionalAttrs config.isoImage.makeEfiBootable {
|
2013-09-04 12:05:09 +01:00
|
|
|
efiBootable = true;
|
|
|
|
efiBootImage = "boot/efi.img";
|
|
|
|
});
|
2009-06-09 13:01:31 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
boot.postBootCommands =
|
|
|
|
''
|
|
|
|
# After booting, register the contents of the Nix store on the
|
|
|
|
# CD in the Nix database in the tmpfs.
|
2013-10-28 15:28:04 +00:00
|
|
|
${config.nix.package}/bin/nix-store --load-db < /nix/store/nix-path-registration
|
2011-09-14 19:20:50 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# nixos-rebuild also requires a "system" profile and an
|
|
|
|
# /etc/NIXOS tag.
|
|
|
|
touch /etc/NIXOS
|
2013-10-28 15:28:04 +00:00
|
|
|
${config.nix.package}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
2013-09-04 12:05:09 +01:00
|
|
|
'';
|
2009-06-05 14:35:27 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
# Add vfat support to the initrd to enable people to copy the
|
2014-07-30 14:44:47 +01:00
|
|
|
# contents of the CD to a bootable USB stick.
|
|
|
|
boot.initrd.supportedFilesystems = [ "vfat" ];
|
2009-06-05 17:02:58 +01:00
|
|
|
|
2013-09-04 12:05:09 +01:00
|
|
|
};
|
2012-03-09 16:17:37 +00:00
|
|
|
|
2009-06-05 14:35:27 +01:00
|
|
|
}
|