* 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 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 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 # !!! Note: we can't use pivot_root here (the kernel gods have
# decreed), but we could use run-init from klibc, which deletes all # decreed), but we could use run-init from klibc, which deletes all
# files in the initramfs, remounts the target root on /, and chroots. # files in the initramfs, remounts the target root on /, and chroots.
cd /mnt/root cd "$targetRoot"
mount --move . / mount --move . /
umount /proc # cleanup umount /proc # cleanup
umount /sys umount /sys

View File

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

View File

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

View File

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

View File

@ -11,10 +11,15 @@ rec {
boot = { boot = {
autoDetectRootDevice = true; autoDetectRootDevice = true;
readOnlyRoot = true; isLiveCD = true;
# The label used to identify the installation CD. # The label used to identify the installation CD.
rootLabel = "NIXOS"; rootLabel = "NIXOS";
extraTTYs = [7 8]; # manual, rogue extraTTYs = [7 8]; # manual, rogue
initrd = {
extraKernelModules = [
"unionfs" # needed for live-CD operation
];
};
}; };
services = { services = {
@ -48,6 +53,7 @@ rec {
# Show the NixOS manual on tty7. # Show the NixOS manual on tty7.
{ name = "manual"; { name = "manual";
job = " job = "
env HOME=/root
start on udev start on udev
stop on shutdown stop on shutdown
respawn ${pkgs.w3m}/bin/w3m ${manual} < /dev/tty7 > /dev/tty7 2>&1 respawn ${pkgs.w3m}/bin/w3m ${manual} < /dev/tty7 > /dev/tty7 2>&1
@ -58,6 +64,7 @@ rec {
# for the installation to finish. # for the installation to finish.
{ name = "rogue"; { name = "rogue";
job = " job = "
env HOME=/root
start on udev start on udev
stop on shutdown stop on shutdown
respawn ${pkgs.rogue}/bin/rogue < /dev/tty8 > /dev/tty8 2>&1 respawn ${pkgs.rogue}/bin/rogue < /dev/tty8 > /dev/tty8 2>&1
@ -112,6 +119,7 @@ rec {
pkgs.vim pkgs.vim
pkgs.subversion # for nixos-checkout pkgs.subversion # for nixos-checkout
pkgs.w3m # needed for the manual anyway 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!"; 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 # 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 # CD. We put them in a tarball because accessing that many small
# files from a slow device like a CD-ROM takes too long. # files from a slow device like a CD-ROM takes too long.
@ -213,15 +212,15 @@ rec {
{ source = system.config.boot.grubSplashImage; { source = system.config.boot.grubSplashImage;
target = "boot/background.xpm.gz"; target = "boot/background.xpm.gz";
} }
{ source = cdMountPoints;
target = "/";
}
{ source = nixosTarball + "/" + nixosTarball.tarName; { source = nixosTarball + "/" + nixosTarball.tarName;
target = "/" + nixosTarball.tarName; target = "/" + nixosTarball.tarName;
} }
{ source = nixpkgsTarball; { source = nixpkgsTarball;
target = "/nixpkgs.tar.bz2"; target = "/nixpkgs.tar.bz2";
} }
{ source = pkgs.writeText "label" "";
target = "/${configuration.boot.rootLabel}";
}
]; ];
# Closures to be copied to the Nix store on the CD. # Closures to be copied to the Nix store on the CD.

View File

@ -20,7 +20,7 @@ if test -n "$bootable"; then
fi fi
done 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 fi
touch pathlist touch pathlist
@ -59,7 +59,7 @@ cat pathlist
# !!! -f is a quick hack. # !!! -f is a quick hack.
ensureDir $out/iso ensureDir $out/iso
genisoimage -r -J -o $out/iso/$isoName $bootFlags \ 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 ensureDir $out/nix-support
echo $system > $out/nix-support/system echo $system > $out/nix-support/system

View File

@ -104,22 +104,24 @@ fi
# Set up Nix. # Set up Nix.
if test -z "@readOnlyRoot@"; then mkdir -p /nix/etc/nix
mkdir -p /nix/etc/nix ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf
ln -sfn /etc/nix.conf /nix/etc/nix/nix.conf chown root.nixbld /nix/store
chown root.nixbld /nix/store chmod 1775 /nix/store
chmod 1775 /nix/store
fi
# Nix initialisation. # Nix initialisation.
mkdir -m 0755 -p /nix/var/nix/db mkdir -m 0755 -p \
mkdir -m 0755 -p /nix/var/nix/gcroots /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 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 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/profiles /nix/var/nix/gcroots/
ln -sf /nix/var/nix/manifests /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; default = false;
description = " description = "
Whether the root device is read-only. This should be set when If set to true, the root device will be mounted read-only and
booting from CD-ROM. 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 (pkgs) substituteAll;
inherit (pkgsDiet) module_init_tools; inherit (pkgsDiet) module_init_tools;
inherit extraUtils; inherit extraUtils;
autoDetectRootDevice = config.boot.autoDetectRootDevice; inherit (config.boot) autoDetectRootDevice isLiveCD;
fileSystems = fileSystems =
pkgs.lib.filter pkgs.lib.filter
(fs: fs.mountPoint == "/" || (fs ? neededForBoot && fs.neededForBoot)) (fs: fs.mountPoint == "/" || (fs ? neededForBoot && fs.neededForBoot))
@ -298,7 +298,6 @@ rec {
isExecutable = true; isExecutable = true;
inherit etc wrapperDir systemPath modprobe defaultShell kernel; inherit etc wrapperDir systemPath modprobe defaultShell kernel;
readOnlyRoot = config.boot.readOnlyRoot;
hostName = config.networking.hostName; hostName = config.networking.hostName;
setuidPrograms = setuidPrograms =
config.security.setuidPrograms ++ config.security.setuidPrograms ++
@ -323,7 +322,7 @@ rec {
inherit (pkgs) substituteAll writeText coreutils inherit (pkgs) substituteAll writeText coreutils
utillinux udev upstart; utillinux udev upstart;
inherit kernel activateConfiguration; inherit kernel activateConfiguration;
readOnlyRoot = config.boot.readOnlyRoot; inherit (config.boot) isLiveCD;
upstartPath = [ upstartPath = [
pkgs.coreutils pkgs.coreutils
pkgs.findutils pkgs.findutils
@ -359,8 +358,7 @@ rec {
inherit (pkgs) grub coreutils gnused gnugrep diffutils findutils upstart; inherit (pkgs) grub coreutils gnused gnugrep diffutils findutils upstart;
grubDevice = config.boot.grubDevice; grubDevice = config.boot.grubDevice;
kernelParams = kernelParams =
(config.boot.kernelParams) ++ config.boot.kernelParams ++ config.boot.extraKernelParams;
(config.boot.extraKernelParams);
inherit bootStage2; inherit bootStage2;
inherit activateConfiguration; inherit activateConfiguration;
inherit grubMenuBuilder; inherit grubMenuBuilder;