[Nix-dev] Looking for patch review "minimal bootable image"
Marc Weber
marco-oweber at gmx.de
Thu Mar 12 23:31:36 CET 2009
I've had some trouble installing nixos on a vservers.
That's why I've added a file installer/bootstrapping-nixos-minimal.nix.
HAve a look at the steps a) -> d) below to see how easy it is installing
nixos without a live cd.
Things to improve: don't include > 100 MB glibc library. That's nearly
impossible to upload that image to a server if you have a slow internet
connection. (You can always build the image on the server yourself..)
Maybe this was already possibled and I've just missed it?
Is it worth adding to the manual ?
Sincerly
Marc Weber
diff --git a/installer/bootstrapping-nixos-minimal.nix b/installer/bootstrapping-nixos-minimal.nix
new file mode 100644
index 0000000..9d116b3
--- /dev/null
+++ b/installer/bootstrapping-nixos-minimal.nix
@@ -0,0 +1,132 @@
+# using isos is not feasable for some targets.
+# so this file let's you create a minimal tar.gz which contains
+# a minimal nix system into which you can chroot to build the missing parts
+
+/* usage
+
+ create the image by
+ a) nix-build installer/bootstrapping-nixos-minimal.nix -A minimalSystem --arg nixpkgsPath ../nixpkgs
+ b) copy result/bootstrap-nixos.tar.bz2 to the final machine untar it into
+ your $target location
+ c) get a copy of nixos, nixpkgs,services and put them into
+ /etc/nixos/{nixpkgs,nixos,services} as usual
+ d) create /etc/nixos/configuration.nix
+ d) chroot $target ./start-bootsrapping-env.sh
+
+ finally)
+ rm ./start-bootstrapping-env.sh
+
+
+FIXME: it should be enough to just unpack the final bootstrapping system.
+ Registering store paths is no longer necessary because bdb is no longer
+ required!
+*/
+
+{ platform ? __currentSystem
+, relName ?
+ if builtins.pathExists ../../relname
+ then builtins.readFile ../../relname
+ else "nixos-${builtins.readFile ../../VERSION}"
+, nixpkgsPath ? ../../../nixpkgs
+}:
+
+rec {
+
+
+ pkgs = import "${nixpkgsPath}/pkgs/top-level/all-packages.nix" {system = platform;};
+
+
+ # makeProg is copied from installer/default.nix (FIXME: remove duplication!)
+ makeProg = args: pkgs.substituteAll (args // {
+ dir = "bin";
+ isExecutable = true;
+ });
+
+ minimalSystem = {
+ extraPackages ? [] # maybe you want to include nano or such. This might increase final size very much!
+ }:
+ let
+
+ bash = "";
+
+ pathsFromGraph = "${nixpkgsPath}/pkgs/build-support/kernel/paths-from-graph.pl";
+
+ nixosBootstrapInstall = makeProg {
+ name = "nixos-install-bootstrap";
+ src = ./nixos-install.sh;
+ inherit pathsFromGraph;
+
+ inherit (pkgs) nixUnstable;
+ perl = "PERL_NOT_USED";
+ nixpkgsURL = http://nixos.org/releases/nixpkgs/unstable; # TODO don't duplicate this url that often!
+
+ nixClosure="NOT_USED";
+ };
+ bootStrappingEnv = pkgs.buildEnv {
+ name = "nix-and-sh";
+ paths = [
+ # list partially duplicated (-> installer/default.nix)
+ pkgs.nixUnstable
+ bash
+ pkgs.coreutils # (? remove ?) coreutils so that we can do most work within the chroot
+ pkgs.pwdutils # is used to set the password of the inital root account
+ nixosBootstrapInstall
+ ];
+ };
+ nixBootstrappingEnvClosure = pkgs.runCommand "closure"
+ {exportReferencesGraph = ["refs" bootStrappingEnv];}
+ "cp refs $out";
+
+ in
+ pkgs.stdenv.mkDerivation {
+ name = "bootstrapping-nixos-archive";
+ buildInputs = [pkgs.perl];
+ phases = "buildPhase";
+ # copy nix closure, installation script + start env script into a image directory then pack it to $out/installer/
+ buildPhase = ''
+ mkdir image; cd image;
+
+ # include minimal system
+ storePaths=$(perl ${pathsFromGraph} ${nixBootstrappingEnvClosure})
+ cp ${nixBootstrappingEnvClosure} nixClosure # ensure the script can find it without using perl!
+
+ echo "copying store paths: $storePaths"
+ cp -r $storePaths .
+
+ cat >> start-boot-strapping-env.sh << EOF
+ !#${bash}/bin/bash
+ echo "at this stage you should have setup the following locations. You can override the env vars if you like:"
+ echo "Probably you should also have mount --(r)bound: /dev /sys /proc"
+
+ export NIXOS=/etc/nixos/nixos
+ export NIXPKGS=/etc/nixos/nixos
+ export NIXOS_CONFIG=/etc/nixos/configuration.nix
+ export mountPoint=./
+
+ for var in NIXOS NIXPKGS NIXOS_CONFIG mountPoint; do
+ echo "$var=''${!var}"
+ done
+
+ export PATH=''${bootStrappingEnv}/bin
+ export BOOTSTRAPPING_FROM_MINIMAL_SYSTEM=1
+ export NIXOS_INSTALL_GRUB=0
+ echo "the following environment variables have been set for you as well:"
+ for var in PATH BOOTSTRAPPING_FROM_MINIMAL_SYSTEM NIXOS_INSTALL_GRUB; do
+ echo "$var=''${!var}"
+ done
+
+ echo
+ echo "Additionally you can export NIX_OTHER_STORES to speed up installation"
+ echo
+ echo "now run nixos-bootstrap-install to install the basic nixos system"
+ echo "after that set the root password using:"
+ echo "echo $YOUR_PASSWORD | passwd --stdin root"
+ exec bash
+ EOF
+ chmod +x start-boot-strapping-env.sh
+
+ ensureDir $out/installer
+ tar cjf $out/installer/bootstrapping-nixos-archive.tar.bz2 .
+ '';
+ };
+}
diff --git a/installer/nixos-install.sh b/installer/nixos-install.sh
index 1288304..c05c4f4 100644
--- a/installer/nixos-install.sh
+++ b/installer/nixos-install.sh
@@ -9,6 +9,9 @@
# * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration>
# * run the activation script of the configuration (also installs Grub)
+# BOOTSTRAPPING_FROM_MINIMAL_SYSTEM will be set in bootstrapping-nixos-minimal.nix
+# it indicates that the minimal closure has been extracted to $mountPoint = `pwd`
+
set -e
if test -z "$mountPoint"; then
@@ -43,7 +46,8 @@ if ! test -e "$mountPoint/$NIXOS_CONFIG"; then
echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist"
exit 1
fi
-
+
+NIXOS_INSTALL_GRUB=${NIXOS_INSTALL_GRUB:-1}
NIXOS=$(readlink -f "$NIXOS")
@@ -55,10 +59,13 @@ cp /etc/resolv.conf $mountPoint/etc/
# Mount some stuff in the target root directory.
mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/mnt
-mount --bind /dev $mountPoint/dev
-mount --bind /proc $mountPoint/proc
-mount --bind /sys $mountPoint/sys
-mount --rbind / $mountPoint/mnt
+
+if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM" ]; then
+ mount --bind /dev $mountPoint/dev
+ mount --bind /proc $mountPoint/proc
+ mount --bind /sys $mountPoint/sys
+ mount --rbind / $mountPoint/mnt
+fi
umountUnder() {
local dir="$1"
@@ -71,6 +78,9 @@ umountUnder() {
}
cleanup() {
+ # user must cleanup when $BOOTSTRAPPING_FROM_MINIMAL_SYSTEM is is set. This
+ # script hasn't mounted anything itself in that case
+ [ -n "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM"] && return
umountUnder $mountPoint/mnt
umountUnder $mountPoint/dev
umountUnder $mountPoint/proc
@@ -97,17 +107,26 @@ mkdir -m 0755 -p \
mkdir -m 1777 -p \
$mountPoint/nix/store \
+if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM" ]; then
+ # Get the store paths to copy from the references graph.
+ storePaths=$(@perl@/bin/perl @pathsFromGraph@ @nixClosure@)
-# 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"
+ rsync -a $i $mountPoint/nix/store/
+ done
+fi
-# Copy Nix to the Nix store on the target device.
-echo "copying Nix to $mountPoint...."
-for i in $storePaths; do
- echo " $i"
- rsync -a $i $mountPoint/nix/store/
-done
+my_chroot(){
+ if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM"]; then
+ chroot $mountPoint "$@"
+ else
+ "$@"
+ fi
+}
# Register the paths in the Nix closure as valid. This is necessary
@@ -115,7 +134,11 @@ done
# 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@
+if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM"]; then
+ my_chroot @nix@/bin/nix-store --register-validity < @nixClosure@
+else
+ @nix@/bin/nix-store --register-validity < /nixClosure
+fi
# Create the required /bin/sh symlink; otherwise lots of things
@@ -132,48 +155,59 @@ export NIX_OTHER_STORES=/mnt/nix:$NIX_OTHER_STORES
# Do a nix-pull to speed up building.
if test -n "@nixpkgsURL@"; then
- chroot $mountPoint @nix@/bin/nix-pull @nixpkgsURL@/MANIFEST || true
+ my_chroot @nix@/bin/nix-pull @nixpkgsURL@/MANIFEST || true
fi
# Build the specified Nix expression in the target store and install
# it into the system configuration profile.
+if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM"]; then
+ SYSTEM_NIX="/mnt$NIXOS/system/system.nix"
+else
+ SYSTEM_NIX="$NIXOS/system/system.nix"
+fi
+
+
echo "building the system configuration..."
-chroot $mountPoint @nix@/bin/nix-env \
+my_chroot @nix@/bin/nix-env \
-p /nix/var/nix/profiles/system \
- -f "/mnt$NIXOS/system/system.nix" \
+ -f "$SYSTEM_NIX" \
--arg configuration "import $NIXOS_CONFIG" \
--set -A system
-# Make a backup of the old NixOS/Nixpkgs sources.
-echo "copying NixOS/Nixpkgs sources to /etc/nixos...."
+if [ -z "$BOOTSTRAPPING_FROM_MINIMAL_SYSTEM"]; then
-backupTimestamp=$(date "+%Y%m%d%H%M%S")
+ # Make a backup of the old NixOS/Nixpkgs sources.
+ echo "copying NixOS/Nixpkgs sources to /etc/nixos...."
-targetNixos=$mountPoint/etc/nixos/nixos
-if test -e $targetNixos; then
- mv $targetNixos $targetNixos.backup-$backupTimestamp
-fi
+ backupTimestamp=$(date "+%Y%m%d%H%M%S")
-targetNixpkgs=$mountPoint/etc/nixos/nixpkgs
-if test -e $targetNixpkgs; then
- mv $targetNixpkgs $targetNixpkgs.backup-$backupTimestamp
-fi
+ targetNixos=$mountPoint/etc/nixos/nixos
+ if test -e $targetNixos; then
+ mv $targetNixos $targetNixos.backup-$backupTimestamp
+ fi
-targetServices=$mountPoint/etc/nixos/services
-if test -e $targetServices; then
- mv $targetServices $targetServices.backup-$backupTimestamp
-fi
+ targetNixpkgs=$mountPoint/etc/nixos/nixpkgs
+ if test -e $targetNixpkgs; then
+ mv $targetNixpkgs $targetNixpkgs.backup-$backupTimestamp
+ fi
+ targetServices=$mountPoint/etc/nixos/services
+ if test -e $targetServices; then
+ mv $targetServices $targetServices.backup-$backupTimestamp
+ fi
+
+
+ # Copy the NixOS/Nixpkgs sources to the target.
+ cp -prd $NIXOS $targetNixos
+ if test -e /etc/nixos/nixpkgs; then
+ cp -prd /etc/nixos/nixpkgs $targetNixpkgs
+ fi
+ if test -e /etc/nixos/services; then
+ cp -prd /etc/nixos/services $targetServices
+ fi
-# Copy the NixOS/Nixpkgs sources to the target.
-cp -prd $NIXOS $targetNixos
-if test -e /etc/nixos/nixpkgs; then
- cp -prd /etc/nixos/nixpkgs $targetNixpkgs
-fi
-if test -e /etc/nixos/services; then
- cp -prd /etc/nixos/services $targetServices
fi
@@ -190,5 +224,5 @@ touch $mountPoint/etc/NIXOS
# a menu default pointing at the kernel/initrd/etc of the new
# configuration.
echo "finalising the installation..."
-NIXOS_INSTALL_GRUB=1 chroot $mountPoint \
+NIXOS_INSTALL_GRUB=$NIXOS_INSTALL_GRUB chroot $mountPoint \
/nix/var/nix/profiles/system/bin/switch-to-configuration boot
More information about the nix-dev
mailing list