* Use unionfs to provide a real Live CD, i.e., the files on the CD

appear writable (though all writes go to a tmpfs).  This allows you
  to run Nix operations on the Live CD.  However, we're not quite
  there yet since the CD doesn't have a valid Nix database.  So for
  instance a garbage collect will cause everything to be deleted,
  hanging the system.

svn path=/nixos/trunk/; revision=10276
This commit is contained in:
Eelco Dolstra 2008-01-24 16:56:09 +00:00
parent 7fa31be440
commit 49e8829053
9 changed files with 72 additions and 63 deletions

View file

@ -211,6 +211,19 @@ else
fi
# If this is a live-CD/DVD, then union-mount a tmpfs on top of the
# original root.
targetRoot=/mnt/root
if test -n "@isLiveCD@"; then
mkdir /mnt/tmpfs
mount -n -t tmpfs -o "mode=755" none /mnt/tmpfs
mkdir /mnt/union
mount -t unionfs -o dirs=/mnt/tmpfs=rw:$targetRoot=ro none /mnt/union
targetRoot=/mnt/union
fi
if test -n "$debug1mounts"; then fail; fi
@ -218,7 +231,7 @@ if test -n "$debug1mounts"; then fail; fi
# !!! Note: we can't use pivot_root here (the kernel gods have
# decreed), but we could use run-init from klibc, which deletes all
# files in the initramfs, remounts the target root on /, and chroots.
cd /mnt/root
cd "$targetRoot"
mount --move . /
umount /proc # cleanup
umount /sys

View file

@ -20,8 +20,12 @@
# must at least be a file system for the / mount point in this list.
fileSystems ? []
# If scanning, we need a disk label.
, rootLabel
, # If scanning, we need a disk label.
rootLabel
, # Whether the root device is read-only and should be made writable
# through a unionfs.
isLiveCD
, # The path of the stage 2 init to call once we've mounted the root
# device.
@ -44,7 +48,7 @@ substituteAll {
src = ./boot-stage-1-init.sh;
isExecutable = true;
inherit staticShell modules modulesDir;
inherit autoDetectRootDevice mountPoints devices fsTypes optionss;
inherit autoDetectRootDevice isLiveCD mountPoints devices fsTypes optionss;
rootLabel = if autoDetectRootDevice then rootLabel else "";
path = [
staticTools

View file

@ -25,19 +25,9 @@ setPath "@path@"
# Mount special file systems.
needWritableDir() {
if test -n "@readOnlyRoot@"; then
mount -t tmpfs -o "mode=$2" none $1 $3
else
mkdir -m $2 -p $1
fi
}
needWritableDir /etc 0755 -n # to shut up mount
test -e /etc/fstab || touch /etc/fstab # idem
mkdir -m 0755 -p /etc
test -e /etc/fstab || touch /etc/fstab # to shut up mount
mkdir -m 0755 -p /proc
mount -n -t proc none /proc
cat /proc/mounts > /etc/mtab
@ -71,19 +61,20 @@ done
# More special file systems, initialise required directories.
mkdir -m 0755 -p /sys
mount -t sysfs none /sys
mkdir -m 0755 -p /dev
mount -t tmpfs -o "mode=0755" none /dev
mkdir -m 0755 -p /dev/pts
mount -t devpts none /dev/pts
mount -t usbfs none /proc/bus/usb
needWritableDir /tmp 01777
needWritableDir /var 0755
needWritableDir /nix/var 0755
needWritableDir /root 0700
needWritableDir /bin 0755 # for the /bin/sh symlink
if test -d /home ; then
needWritableDir /home 0777
fi
mkdir -m 01777 /tmp
mkdir -m 0755 /var
mkdir -m 0755 /nix/var
mkdir -m 0700 /root
mkdir -m 0755 /bin # for the /bin/sh symlink
mkdir -m 0755 /home
# Miscellaneous boot time cleanup.
rm -rf /var/run

View file

@ -2,9 +2,9 @@
, utillinux, kernel, udev, upstart
, activateConfiguration
, # Whether the root device is root only. If so, we'll mount a
# ramdisk on /etc, /var and so on.
readOnlyRoot
, # Whether the root device is read-only and should be made writable
# through a unionfs.
isLiveCD
, # Path for Upstart jobs. Should be quite minimal.
upstartPath
@ -16,7 +16,7 @@
substituteAll {
src = ./boot-stage-2-init.sh;
isExecutable = true;
inherit kernel upstart readOnlyRoot activateConfiguration upstartPath;
inherit kernel upstart isLiveCD activateConfiguration upstartPath;
path = [
coreutils
utillinux

View file

@ -11,10 +11,15 @@ rec {
boot = {
autoDetectRootDevice = true;
readOnlyRoot = true;
isLiveCD = true;
# The label used to identify the installation CD.
rootLabel = "NIXOS";
extraTTYs = [7 8]; # manual, rogue
initrd = {
extraKernelModules = [
"unionfs" # needed for live-CD operation
];
};
};
services = {
@ -48,6 +53,7 @@ rec {
# Show the NixOS manual on tty7.
{ name = "manual";
job = "
env HOME=/root
start on udev
stop on shutdown
respawn ${pkgs.w3m}/bin/w3m ${manual} < /dev/tty7 > /dev/tty7 2>&1
@ -58,6 +64,7 @@ rec {
# for the installation to finish.
{ name = "rogue";
job = "
env HOME=/root
start on udev
stop on shutdown
respawn ${pkgs.rogue}/bin/rogue < /dev/tty8 > /dev/tty8 2>&1
@ -112,6 +119,7 @@ rec {
pkgs.vim
pkgs.subversion # for nixos-checkout
pkgs.w3m # needed for the manual anyway
pkgs.gdb # for debugging Nix
];
};
@ -135,15 +143,6 @@ rec {
else pkgs.writeText "dummy-manual" "Manual not included in this build!";
# Since the CD is read-only, the mount points must be on disk.
cdMountPoints = pkgs.runCommand "mount-points" {} "
ensureDir $out
cd $out
mkdir proc sys tmp etc dev var mnt nix nix/var root bin
touch $out/${configuration.boot.rootLabel}
";
# We need a copy of the Nix expressions for Nixpkgs and NixOS on the
# CD. We put them in a tarball because accessing that many small
# files from a slow device like a CD-ROM takes too long.
@ -213,15 +212,15 @@ rec {
{ source = system.config.boot.grubSplashImage;
target = "boot/background.xpm.gz";
}
{ source = cdMountPoints;
target = "/";
}
{ source = nixosTarball + "/" + nixosTarball.tarName;
target = "/" + nixosTarball.tarName;
}
{ source = nixpkgsTarball;
target = "/nixpkgs.tar.bz2";
}
{ source = pkgs.writeText "label" "";
target = "/${configuration.boot.rootLabel}";
}
];
# Closures to be copied to the Nix store on the CD.

View file

@ -20,7 +20,7 @@ if test -n "$bootable"; then
fi
done
bootFlags="-b $bootImage -c boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"
bootFlags="-b $bootImage -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"
fi
touch pathlist
@ -59,7 +59,7 @@ cat pathlist
# !!! -f is a quick hack.
ensureDir $out/iso
genisoimage -r -J -o $out/iso/$isoName $bootFlags \
-graft-points -path-list pathlist
-hide-rr-moved -graft-points -path-list pathlist
ensureDir $out/nix-support
echo $system > $out/nix-support/system

View file

@ -104,22 +104,24 @@ fi
# Set up Nix.
if test -z "@readOnlyRoot@"; then
mkdir -p /nix/etc/nix
ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf
chown root.nixbld /nix/store
chmod 1775 /nix/store
fi
mkdir -p /nix/etc/nix
ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf
chown root.nixbld /nix/store
chmod 1775 /nix/store
# Nix initialisation.
mkdir -m 0755 -p /nix/var/nix/db
mkdir -m 0755 -p /nix/var/nix/gcroots
mkdir -m 0755 -p \
/nix/var/nix/gcroots \
/nix/var/nix/temproots \
/nix/var/nix/manifests \
/nix/var/nix/userpool \
/nix/var/nix/profiles \
/nix/var/nix/db \
/nix/var/log/nix/drvs \
/nix/var/nix/channel-cache
mkdir -m 1777 -p /nix/var/nix/gcroots/per-user
mkdir -m 0755 -p /nix/var/nix/temproots
mkdir -m 0755 -p /nix/var/nix/profiles
mkdir -m 1777 -p /nix/var/nix/profiles/per-user
mkdir -m 0755 -p /nix/var/nix/channel-cache
ln -sf /nix/var/nix/profiles /nix/var/nix/gcroots/
ln -sf /nix/var/nix/manifests /nix/var/nix/gcroots/

View file

@ -25,11 +25,13 @@
";
};
readOnlyRoot = mkOption {
isLiveCD = mkOption {
default = false;
description = "
Whether the root device is read-only. This should be set when
booting from CD-ROM.
If set to true, the root device will be mounted read-only and
a ramdisk will be mounted on top of it using unionfs to
provide a writable root. This is used for the NixOS
Live-CD/DVD.
";
};

View file

@ -78,7 +78,7 @@ rec {
inherit (pkgs) substituteAll;
inherit (pkgsDiet) module_init_tools;
inherit extraUtils;
autoDetectRootDevice = config.boot.autoDetectRootDevice;
inherit (config.boot) autoDetectRootDevice isLiveCD;
fileSystems =
pkgs.lib.filter
(fs: fs.mountPoint == "/" || (fs ? neededForBoot && fs.neededForBoot))
@ -298,7 +298,6 @@ rec {
isExecutable = true;
inherit etc wrapperDir systemPath modprobe defaultShell kernel;
readOnlyRoot = config.boot.readOnlyRoot;
hostName = config.networking.hostName;
setuidPrograms =
config.security.setuidPrograms ++
@ -323,7 +322,7 @@ rec {
inherit (pkgs) substituteAll writeText coreutils
utillinux udev upstart;
inherit kernel activateConfiguration;
readOnlyRoot = config.boot.readOnlyRoot;
inherit (config.boot) isLiveCD;
upstartPath = [
pkgs.coreutils
pkgs.findutils
@ -359,8 +358,7 @@ rec {
inherit (pkgs) grub coreutils gnused gnugrep diffutils findutils upstart;
grubDevice = config.boot.grubDevice;
kernelParams =
(config.boot.kernelParams) ++
(config.boot.extraKernelParams);
config.boot.kernelParams ++ config.boot.extraKernelParams;
inherit bootStage2;
inherit activateConfiguration;
inherit grubMenuBuilder;