[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