diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-10-10 13:28:20 +0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-10-10 13:28:20 +0200 |
commit | 5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010 (patch) | |
tree | a6c0f605be6de3f372ae69905b331f9f75452da7 /nixos/modules/installer/tools | |
parent | 6070bc016bd2fd945b04347e25cfd3738622d2ac (diff) | |
download | nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.gz nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.bz2 nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.lz nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.xz nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.tar.zst nixlib-5c1f8cbc70cd5e6867ef6a2a06d27a40daa07010.zip |
Move all of NixOS to nixos/ in preparation of the repository merge
Diffstat (limited to 'nixos/modules/installer/tools')
-rw-r--r-- | nixos/modules/installer/tools/get-version-suffix | 29 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-build-vms/build-vms.nix | 9 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh | 62 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-checkout.nix | 55 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-gen-seccure-keys.sh | 13 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-hardware-scan.pl | 248 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-install.sh | 238 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-option.sh | 395 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-rebuild.sh | 222 | ||||
-rw-r--r-- | nixos/modules/installer/tools/nixos-version.sh | 2 | ||||
-rw-r--r-- | nixos/modules/installer/tools/tools.nix | 112 |
11 files changed, 1385 insertions, 0 deletions
diff --git a/nixos/modules/installer/tools/get-version-suffix b/nixos/modules/installer/tools/get-version-suffix new file mode 100644 index 000000000000..76cec8d5dae3 --- /dev/null +++ b/nixos/modules/installer/tools/get-version-suffix @@ -0,0 +1,29 @@ +getVersion() { + local dir="$1" + rev= + if [ -e "$dir/.git" ]; then + if [ -z "$(type -P git)" ]; then + echo "warning: Git not found; cannot figure out revision of $dir" >&2 + return + fi + cd "$dir" + rev=$(git rev-parse --short HEAD) + if git describe --always --dirty | grep -q dirty; then + rev+=M + fi + fi +} + +if nixos=$(nix-instantiate --find-file nixos "$@"); then + getVersion $nixos + if [ -n "$rev" ]; then + suffix="pre-$rev" + if nixpkgs=$(nix-instantiate --find-file nixpkgs "$@"); then + getVersion $nixpkgs + if [ -n "$rev" ]; then + suffix+="-$rev" + fi + fi + echo $suffix + fi +fi diff --git a/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix new file mode 100644 index 000000000000..5e77b701ff5a --- /dev/null +++ b/nixos/modules/installer/tools/nixos-build-vms/build-vms.nix @@ -0,0 +1,9 @@ +{ system ? builtins.currentSystem +, networkExpr +}: + +let nodes = import networkExpr; in + +with import ../../../../lib/testing.nix { inherit system; }; + +(complete { inherit nodes; testScript = ""; }).driver diff --git a/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh new file mode 100644 index 000000000000..0a6e8b920a11 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-build-vms/nixos-build-vms.sh @@ -0,0 +1,62 @@ +#! @shell@ -e + +# Shows the usage of this command to the user + +showUsage() +{ + echo "Usage: $0 network_expr" + echo "Options:" + echo + echo "--no-out-link Do not create a 'result' symlink" + echo "--show-trace Shows the output trace" + echo "-h,--help Shows the usage of this command" +} + +# Parse valid argument options + +PARAMS=`getopt -n $0 -o h -l no-out-link,show-trace,help -- "$@"` + +if [ $? != 0 ] +then + showUsage + exit 1 +fi + +eval set -- "$PARAMS" + +# Evaluate valid options + +while [ "$1" != "--" ] +do + case "$1" in + --no-out-link) + noOutLinkArg="--no-out-link" + ;; + --show-trace) + showTraceArg="--show-trace" + ;; + -h|--help) + showUsage + exit 0 + ;; + esac + + shift +done + +shift + +# Validate the given options + +if [ "$1" = "" ] +then + echo "ERROR: A network expression must be specified!" >&2 + exit 1 +else + networkExpr=$(readlink -f $1) +fi + +# Build a network of VMs + +nix-build '<nixos/modules/installer/tools/nixos-build-vms/build-vms.nix>' \ + --argstr networkExpr $networkExpr $noOutLinkArg $showTraceArg diff --git a/nixos/modules/installer/tools/nixos-checkout.nix b/nixos/modules/installer/tools/nixos-checkout.nix new file mode 100644 index 000000000000..1a734ca5eeb7 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-checkout.nix @@ -0,0 +1,55 @@ +# This module generates the nixos-checkout script, which replaces the +# NixOS and Nixpkgs source trees in /etc/nixos/{nixos,nixpkgs} with +# Git checkouts. + +{config, pkgs, ...}: + +with pkgs.lib; + +let + + nixosCheckout = pkgs.substituteAll { + name = "nixos-checkout"; + dir = "bin"; + isExecutable = true; + src = pkgs.writeScript "nixos-checkout" + '' + #! ${pkgs.stdenv.shell} -e + + if [ "$1" == "-h" ] || [ "$1" == "--help" ]; then + echo "Usage: `basename $0` [PREFIX]. See NixOS Manual for more info." + exit 0 + fi + + prefix="$1" + if [ -z "$prefix" ]; then prefix=/etc/nixos; fi + mkdir -p "$prefix" + cd "$prefix" + + if [ -z "$(type -P git)" ]; then + echo "installing Git..." + nix-env -iA nixos.pkgs.git || nix-env -i git + fi + + # Move any old nixos or nixpkgs directories out of the way. + backupTimestamp=$(date "+%Y%m%d%H%M%S") + + if [ -e nixos -a ! -e nixos/.git ]; then + mv nixos nixos-$backupTimestamp + fi + + if [ -e nixpkgs -a ! -e nixpkgs/.git ]; then + mv nixpkgs nixpkgs-$backupTimestamp + fi + + # Check out the NixOS and Nixpkgs sources. + git clone git://github.com/NixOS/nixos.git nixos + git clone git://github.com/NixOS/nixpkgs.git nixpkgs + ''; + }; + +in + +{ + environment.systemPackages = [ nixosCheckout ]; +} diff --git a/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh b/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh new file mode 100644 index 000000000000..a97eef672f7e --- /dev/null +++ b/nixos/modules/installer/tools/nixos-gen-seccure-keys.sh @@ -0,0 +1,13 @@ +#! @shell@ -e + +mkdir -p /var/elliptic-keys +chmod 0755 /var/elliptic-keys +cd /var/elliptic-keys +touch private +chmod 0700 private +dd if=/dev/urandom bs=128 count=1 of=private +chmod 0500 private +public=$(seccure-key -F private 2>&1) +echo ${public#*The public key is: } > public +chmod 0555 public + diff --git a/nixos/modules/installer/tools/nixos-hardware-scan.pl b/nixos/modules/installer/tools/nixos-hardware-scan.pl new file mode 100644 index 000000000000..3204f3d40512 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-hardware-scan.pl @@ -0,0 +1,248 @@ +#! @perl@/bin/perl -w + +use File::Spec; +use File::Basename; + + +my @attrs = (); +my @kernelModules = (); +my @initrdKernelModules = (); +my @modulePackages = (); +my @imports = ("<nixos/modules/installer/scan/not-detected.nix>"); + + +sub debug { + return unless defined $ENV{"DEBUG"}; + print STDERR @_; +} + + +# Read a file, returning undef if the file cannot be opened. +sub readFile { + my $filename = shift; + my $res; + if (open FILE, "<$filename") { + my $prev = $/; + undef $/; + $res = <FILE>; + $/ = $prev; + close FILE; + chomp $res; + } + return $res; +} + + +my $cpuinfo = readFile "/proc/cpuinfo"; + + +sub hasCPUFeature { + my $feature = shift; + return $cpuinfo =~ /^flags\s*:.* $feature( |$)/m; +} + + +# Detect the number of CPU cores. +my $cpus = scalar (grep {/^processor\s*:/} (split '\n', $cpuinfo)); + + +# Virtualization support? +push @kernelModules, "kvm-intel" if hasCPUFeature "vmx"; +push @kernelModules, "kvm-amd" if hasCPUFeature "svm"; + + +# Look at the PCI devices and add necessary modules. Note that most +# modules are auto-detected so we don't need to list them here. +# However, some are needed in the initrd to boot the system. + +my $videoDriver; + +sub pciCheck { + my $path = shift; + my $vendor = readFile "$path/vendor"; + my $device = readFile "$path/device"; + my $class = readFile "$path/class"; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $vendor $device $class"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + # See the bottom of http://pciids.sourceforge.net/pci.ids for + # device classes. + if (# Mass-storage controller. Definitely important. + $class =~ /^0x01/ || + + # Firewire controller. A disk might be attached. + $class =~ /^0x0c00/ || + + # USB controller. Needed if we want to use the + # keyboard when things go wrong in the initrd. + $class =~ /^0x0c03/ + ) + { + push @initrdKernelModules, $module; + } + } + + # broadcom STA driver (wl.ko) + # list taken from http://www.broadcom.com/docs/linux_sta/README.txt + if ($vendor eq "0x14e4" && + ($device eq "0x4311" || $device eq "0x4312" || $device eq "0x4313" || + $device eq "0x4315" || $device eq "0x4327" || $device eq "0x4328" || + $device eq "0x4329" || $device eq "0x432a" || $device eq "0x432b" || + $device eq "0x432c" || $device eq "0x432d" || $device eq "0x4353" || + $device eq "0x4357" || $device eq "0x4358" || $device eq "0x4359" ) ) + { + push @modulePackages, "config.boot.kernelPackages.broadcom_sta"; + push @kernelModules, "wl"; + } + + # Can't rely on $module here, since the module may not be loaded + # due to missing firmware. Ideally we would check modules.pcimap + # here. + push @attrs, "networking.enableIntel2200BGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x1043" || $device eq "0x104f" || $device eq "0x4220" || + $device eq "0x4221" || $device eq "0x4223" || $device eq "0x4224"); + + push @attrs, "networking.enableIntel3945ABGFirmware = true;" if + $vendor eq "0x8086" && + ($device eq "0x4229" || $device eq "0x4230" || + $device eq "0x4222" || $device eq "0x4227"); + + # Assume that all NVIDIA cards are supported by the NVIDIA driver. + # There may be exceptions (e.g. old cards). + $videoDriver = "nvidia" if $vendor eq "0x10de" && $class =~ /^0x03/; +} + +foreach my $path (glob "/sys/bus/pci/devices/*") { + pciCheck $path; +} + + +# Idem for USB devices. + +sub usbCheck { + my $path = shift; + my $class = readFile "$path/bInterfaceClass"; + my $subclass = readFile "$path/bInterfaceSubClass"; + my $protocol = readFile "$path/bInterfaceProtocol"; + + my $module; + if (-e "$path/driver/module") { + $module = basename `readlink -f $path/driver/module`; + chomp $module; + } + + debug "$path: $class $subclass $protocol"; + debug " $module" if defined $module; + debug "\n"; + + if (defined $module) { + if (# Mass-storage controller. Definitely important. + $class eq "08" || + + # Keyboard. Needed if we want to use the + # keyboard when things go wrong in the initrd. + ($class eq "03" && $protocol eq "01") + ) + { + push @initrdKernelModules, $module; + } + } +} + +foreach my $path (glob "/sys/bus/usb/devices/*") { + if (-e "$path/bInterfaceClass") { + usbCheck $path; + } +} + + +# Add the modules for all block devices. + +foreach my $path (glob "/sys/class/block/*") { + my $module; + if (-e "$path/device/driver/module") { + $module = basename `readlink -f $path/device/driver/module`; + chomp $module; + push @initrdKernelModules, $module; + } +} + + +if ($videoDriver) { + push @attrs, "services.xserver.videoDrivers = [ \"$videoDriver\" ];"; +} + + +# Check if we're a VirtualBox guest. If so, enable the guest +# additions. +my $dmi = `@dmidecode@/sbin/dmidecode`; +if ($dmi =~ /Manufacturer: innotek/) { + push @attrs, "services.virtualbox.enable = true;" +} + + +# Generate the configuration file. + +sub removeDups { + my %seen; + my @res = (); + foreach my $s (@_) { + if (!defined $seen{$s}) { + $seen{$s} = ""; + push @res, $s; + } + } + return @res; +} + +sub toNixExpr { + my $res = ""; + foreach my $s (@_) { + $res .= " \"$s\""; + } + return $res; +} + +sub multiLineList { + my $indent = shift; + my $res = ""; + $res = "\n" if scalar @_ > 0; + foreach my $s (@_) { + $res .= "$indent$s\n"; + } + return $res; +} + +my $initrdKernelModules = toNixExpr(removeDups @initrdKernelModules); +my $kernelModules = toNixExpr(removeDups @kernelModules); +my $modulePackages = toNixExpr(removeDups @modulePackages); +my $attrs = multiLineList(" ", removeDups @attrs); +my $imports = multiLineList(" ", removeDups @imports); + + +print <<EOF ; +# This is a generated file. Do not modify! +# Make changes to /etc/nixos/configuration.nix instead. +{ config, pkgs, ... }: + +{ + imports = [$imports ]; + + boot.initrd.kernelModules = [$initrdKernelModules ]; + boot.kernelModules = [$kernelModules ]; + boot.extraModulePackages = [$modulePackages ]; + + nix.maxJobs = $cpus; +$attrs} +EOF +# workaround for a bug in substituteAll diff --git a/nixos/modules/installer/tools/nixos-install.sh b/nixos/modules/installer/tools/nixos-install.sh new file mode 100644 index 000000000000..a4ac5b68dd7f --- /dev/null +++ b/nixos/modules/installer/tools/nixos-install.sh @@ -0,0 +1,238 @@ +#! @shell@ + +# - [mount target device] <- currently disabled +# - make Nix store etc. +# - copy closure of Nix to target device +# - register validity +# - with a chroot to the target device: +# * nix-env -p /nix/var/nix/profiles/system -i <nix-expr for the configuration> +# * run the activation script of the configuration (also installs Grub) + +# Parse the command line for the -I flag +extraBuildFlags=() + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + -I) + given_path="$1"; shift 1 + absolute_path=$(readlink -m $given_path) + extraBuildFlags+=("$i" "/mnt$absolute_path") + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +set -e +shopt -s nullglob + +if test -z "$mountPoint"; then + mountPoint=/mnt +fi + +if test -z "$NIXOS_CONFIG"; then + NIXOS_CONFIG=/etc/nixos/configuration.nix +fi + +if ! test -e "$mountPoint"; then + echo "mount point $mountPoint doesn't exist" + exit 1 +fi + +if ! grep -F -q " $mountPoint " /proc/mounts; then + echo "$mountPoint doesn't appear to be a mount point" + exit 1 +fi + +if ! test -e "$mountPoint/$NIXOS_CONFIG"; then + echo "configuration file $mountPoint/$NIXOS_CONFIG doesn't exist" + exit 1 +fi + + + +# Mount some stuff in the target root directory. We bind-mount /etc +# into the chroot because we need networking and the nixbld user +# accounts in /etc/passwd. But we do need the target's /etc/nixos. +mkdir -m 0755 -p $mountPoint/dev $mountPoint/proc $mountPoint/sys $mountPoint/mnt $mountPoint/mnt2 $mountPoint/mnt-nixos $mountPoint/mnt-nixpkgs $mountPoint/etc /etc/nixos +mount --make-private / # systemd makes / shared, which is annoying +mount --bind / $mountPoint/mnt +mount --bind /nix $mountPoint/mnt/nix +mount --bind /nix/store $mountPoint/mnt/nix/store +mount --bind /dev $mountPoint/dev +mount --bind /dev/shm $mountPoint/dev/shm +mount --bind /proc $mountPoint/proc +mount --bind /sys $mountPoint/sys +mount --bind /sys/firmware/efi/efivars $mountPoint/sys/firmware/efi/efivars &>/dev/null || true +mount --bind $mountPoint/etc/nixos $mountPoint/mnt2 +mount --bind /etc $mountPoint/etc +mount --bind $mountPoint/mnt2 $mountPoint/etc/nixos + +cleanup() { + set +e + mountpoint -q $mountPoint/etc/nixos && umount $mountPoint/etc/nixos + mountpoint -q $mountPoint/etc && umount $mountPoint/etc + umount $mountPoint/mnt2 + umount $mountPoint/mnt-nixos + umount $mountPoint/mnt-nixpkgs + umount $mountPoint/sys/firmware/efi/efivars &>/dev/null || true + umount $mountPoint/sys + umount $mountPoint/proc + umount $mountPoint/dev/shm + umount $mountPoint/dev + umount $mountPoint/mnt/nix/store + umount $mountPoint/mnt/nix + umount $mountPoint/mnt + rmdir $mountPoint/mnt $mountPoint/mnt2 $mountPoint/mnt-nixos $mountPoint/mnt-nixpkgs +} + +trap "cleanup" EXIT + +mkdir -m 01777 -p $mountPoint/tmp +mkdir -m 0755 -p $mountPoint/var + + +# Create the necessary Nix directories on the target device, if they +# don't already exist. +mkdir -m 0755 -p \ + $mountPoint/nix/var/nix/gcroots \ + $mountPoint/nix/var/nix/temproots \ + $mountPoint/nix/var/nix/manifests \ + $mountPoint/nix/var/nix/userpool \ + $mountPoint/nix/var/nix/profiles \ + $mountPoint/nix/var/nix/db \ + $mountPoint/nix/var/log/nix/drvs + +mkdir -m 1775 -p $mountPoint/nix/store +build_users_group=$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"build-users-group"};') +if test -n "$build_users_group"; then + chown root:"$build_users_group" $mountPoint/nix/store +else + chown root $mountPoint/nix/store +fi + + +# 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" + chattr -R -i $mountPoint/$i 2> /dev/null || true # clear immutable bit + rsync -a $i $mountPoint/nix/store/ +done + + +# We don't have locale-archive in the chroot, so clear $LANG. +export LANG= +export LC_ALL= +export LC_TIME= + + +# There is no daemon in the chroot +unset NIX_REMOTE + + +# Create a temporary Nix config file that causes the nixbld users to +# be used. +if test -n "$build_users_group"; then + echo "build-users-group = $build_users_group" > $mountPoint/tmp/nix.conf +fi +binary_caches=$(@perl@/bin/perl -I @nix@/lib/perl5/site_perl/*/* -e 'use Nix::Config; Nix::Config::readConfig; print $Nix::Config::config{"binary-caches"};') +if test -n "$binary_caches"; then + echo "binary-caches = $binary_caches" >> $mountPoint/tmp/nix.conf +fi +export NIX_CONF_DIR=/tmp + + +# Register the paths in the Nix closure as valid. This is necessary +# to prevent them from being deleted the first time we install +# 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@ + + +# Create the required /bin/sh symlink; otherwise lots of things +# (notably the system() function) won't work. +mkdir -m 0755 -p $mountPoint/bin +# !!! assuming that @shell@ is in the closure +ln -sf @shell@ $mountPoint/bin/sh + + +if test -n "$NIXOS_PREPARE_CHROOT_ONLY"; then + echo "User requested only to prepare chroot. Exiting." + exit 0 +fi + + +# Make the build below copy paths from the CD if possible. Note that +# /mnt in the chroot is the root of the CD. +export NIX_OTHER_STORES=/mnt/nix:$NIX_OTHER_STORES + +p=@nix@/libexec/nix/substituters +export NIX_SUBSTITUTERS=$p/copy-from-other-stores.pl:$p/download-from-binary-cache.pl + + +# Make manifests available in the chroot. +rm -f $mountPoint/nix/var/nix/manifests/* +for i in /nix/var/nix/manifests/*.nixmanifest; do + chroot $mountPoint @nix@/bin/nix-store -r "$(readlink -f "$i")" > /dev/null + cp -pd "$i" $mountPoint/nix/var/nix/manifests/ +done + + +# Get the absolute path to the NixOS/Nixpkgs sources. +mount --bind $(readlink -f $(nix-instantiate --find-file nixpkgs)) $mountPoint/mnt-nixpkgs +mount --bind $(readlink -f $(nix-instantiate --find-file nixos)) $mountPoint/mnt-nixos + + +# Build the specified Nix expression in the target store and install +# it into the system configuration profile. +echo "building the system configuration..." +NIX_PATH="nixpkgs=/mnt-nixpkgs:nixos=/mnt-nixos:nixos-config=$NIXOS_CONFIG" NIXOS_CONFIG= \ + chroot $mountPoint @nix@/bin/nix-env \ + "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/system -f '<nixos>' --set -A system --show-trace + + +# Copy the NixOS/Nixpkgs sources to the target as the initial contents +# of the NixOS channel. +mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles +mkdir -m 1777 -p $mountPoint/nix/var/nix/profiles/per-user +mkdir -m 0755 -p $mountPoint/nix/var/nix/profiles/per-user/root +srcs=$(nix-env "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -q nixos --no-name --out-path 2>/dev/null || echo -n "") +if test -n "$srcs"; then + echo "copying NixOS/Nixpkgs sources..." + chroot $mountPoint @nix@/bin/nix-env \ + "${extraBuildFlags[@]}" -p /nix/var/nix/profiles/per-user/root/channels -i "$srcs" --quiet +fi +mkdir -m 0700 -p $mountPoint/root/.nix-defexpr +ln -sfn /nix/var/nix/profiles/per-user/root/channels $mountPoint/root/.nix-defexpr/channels + + +# We're done building/downloading, so we don't need the /etc bind +# mount anymore. In fact, below we want to modify the target's /etc. +umount $mountPoint/etc/nixos +umount $mountPoint/etc + + +# Grub needs an mtab. +ln -sfn /proc/mounts $mountPoint/etc/mtab + + +# Mark the target as a NixOS installation, otherwise +# switch-to-configuration will chicken out. +touch $mountPoint/etc/NIXOS + + +# Switch to the new system configuration. This will install Grub with +# a menu default pointing at the kernel/initrd/etc of the new +# configuration. +echo "finalising the installation..." +NIXOS_INSTALL_GRUB=1 chroot $mountPoint \ + /nix/var/nix/profiles/system/bin/switch-to-configuration boot diff --git a/nixos/modules/installer/tools/nixos-option.sh b/nixos/modules/installer/tools/nixos-option.sh new file mode 100644 index 000000000000..7f008d62c249 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-option.sh @@ -0,0 +1,395 @@ +#! @shell@ -e + +# Allow the location of NixOS sources and the system configuration +# file to be overridden. + +: ${mountPoint=/mnt} +: ${NIXOS_CONFIG=/etc/nixos/configuration.nix} +export NIXOS_CONFIG + +usage () { + echo 1>&2 " +Usage: $0 [-v] [-d] [-l] [--xml] OPTION_NAME + $0 --install + +This program allows you to inspect the current value of NixOS +configuration options. It can also generate a basic NixOS +configuration file. + +Options: + + -i | --install Write a template NixOS configuration file to + ${mountPoint:+$mountPoint/}$NIXOS_CONFIG. + -v | --value Display the current value, based on your + configuration. + -d | --description Display the default value, the example and the + description. + -l | --lookup Display where the option is defined and where it + is declared. + --xml Print an XML representation of the result. + Implies -vdl options. + --help Show this message. + +Environment variables affecting $0: + + \$mountPoint Path to the target file system. + \$NIXOS_CONFIG Path to your configuration file. + +" + + exit 1; +} + +##################### +# Process Arguments # +##################### + +desc=false +defs=false +value=false +xml=false +install=false +verbose=false + +option="" + +argfun="" +for arg; do + if test -z "$argfun"; then + case $arg in + -*) + longarg="" + sarg="$arg" + while test "$sarg" != "-"; do + case $sarg in + --*) longarg=$arg; sarg="--";; + -d*) longarg="$longarg --description";; + -v*) longarg="$longarg --value";; + -l*) longarg="$longarg --lookup";; + -i*) longarg="$longarg --install";; + -*) usage;; + esac + # remove the first letter option + sarg="-${sarg#??}" + done + ;; + *) longarg=$arg;; + esac + for larg in $longarg; do + case $larg in + --description) desc=true;; + --value) value=true;; + --lookup) defs=true;; + --xml) xml=true;; + --install) install=true;; + --verbose) verbose=true;; + --help) usage;; + -*) usage;; + *) if test -z "$option"; then + option="$larg" + else + usage + fi;; + esac + done + else + case $argfun in + set_*) + var=$(echo $argfun | sed 's,^set_,,') + eval $var=$arg + ;; + esac + argfun="" + fi +done + +if $xml; then + value=true + desc=true + defs=true +fi + +# --install cannot be used with -d -v -l without option name. +if $value || $desc || $defs && $install && test -z "$option"; then + usage +fi + +generate=false +if ! $defs && ! $desc && ! $value && $install && test -z "$option"; then + generate=true +fi + +if ! $defs && ! $desc; then + value=true +fi + +if $verbose; then + set -x +else + set +x +fi + +############################# +# Process the configuration # +############################# + +evalNix(){ + nix-instantiate - --eval-only "$@" +} + +evalAttr(){ + local prefix=$1 + local suffix=$2 + local strict=$3 + echo "(import <nixos> {}).$prefix${option:+.$option}${suffix:+.$suffix}" | + evalNix ${strict:+--strict} +} + +evalOpt(){ + evalAttr "eval.options" "$@" +} + +evalCfg(){ + evalAttr "config" "$@" +} + +findSources(){ + local suffix=$1 + echo "builtins.map (f: f.source) (import <nixos> {}).eval.options${option:+.$option}.$suffix" | + evalNix --strict +} + +# Given a result from nix-instantiate, recover the list of attributes it +# contains. +attrNames() { + local attributeset=$1 + # sed is used to replace un-printable subset by 0s, and to remove most of + # the inner-attribute set, which reduce the likelyhood to encounter badly + # pre-processed input. + echo "builtins.attrNames $attributeset" | \ + sed 's,<[A-Z]*>,0,g; :inner; s/{[^\{\}]*};/0;/g; t inner;' | \ + evalNix --strict +} + +# map a simple list which contains strings or paths. +nixMap() { + local fun="$1" + local list="$2" + local elem + for elem in $list; do + test $elem = '[' -o $elem = ']' && continue; + $fun $elem + done +} + +if $install; then + NIXOS_CONFIG="$mountPoint$NIXOS_CONFIG" +fi + +if $generate; then + mkdir -p $(dirname "$NIXOS_CONFIG") + + # Scan the hardware and add the result to /etc/nixos/hardware-scan.nix. + hardware_config="${NIXOS_CONFIG%/configuration.nix}/hardware-configuration.nix" + if test -e "$hardware_config"; then + echo "A hardware configuration file exists, generation skipped." + else + echo "Generating a hardware configuration file in $hardware_config..." + nixos-hardware-scan > "$hardware_config" + fi + + if test -e "$NIXOS_CONFIG"; then + echo 1>&2 "error: Cannot generate a template configuration because a configuration file exists." + exit 1 + fi + + nl=" +" + if test -e /sys/firmware/efi/efivars; then + l1=" # Use the gummiboot efi boot loader." + l2=" boot.loader.grub.enable = false;" + l3=" boot.loader.gummiboot.enable = true;" + l4=" boot.loader.efi.canTouchEfiVariables = true;" + # !!! Remove me when nixos is on 3.10 or greater by default + l5=" # EFI booting requires kernel >= 3.10" + l6=" boot.kernelPackages = pkgs.linuxPackages_3_10;" + bootloader_config="$l1$nl$l2$nl$l3$nl$l4$nl$nl$l5$nl$l6" + else + l1=" # Use the Grub2 boot loader." + l2=" boot.loader.grub.enable = true;" + l3=" boot.loader.grub.version = 2;" + l4=" # Define on which hard drive you want to install Grub." + l5=' # boot.loader.grub.device = "/dev/sda";' + bootloader_config="$l1$nl$l2$nl$l3$nl$nl$l4$nl$l5" + fi + + echo "Generating a basic configuration file in $NIXOS_CONFIG..." + + # Generate a template configuration file where the user has to + # fill the gaps. + cat <<EOF > "$NIXOS_CONFIG" +# Edit this configuration file to define what should be installed on +# the system. Help is available in the configuration.nix(5) man page +# or the NixOS manual available on virtual console 8 (Alt+F8). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + boot.initrd.kernelModules = + [ # Specify all kernel modules that are necessary for mounting the root + # filesystem. + # "xfs" "ata_piix" + # fbcon # Uncomment this when EFI booting to see the console before the root partition is mounted + ]; + +$bootloader_config + + # networking.hostName = "nixos"; # Define your hostname. + # networking.wireless.enable = true; # Enables Wireless. + + # Add filesystem entries for each partition that you want to see + # mounted at boot time. This should include at least the root + # filesystem. + + # fileSystems."/".device = "/dev/disk/by-label/nixos"; + + # fileSystems."/data" = # where you want to mount the device + # { device = "/dev/sdb"; # the device + # fsType = "ext3"; # the type of the partition + # options = "data=journal"; + # }; + + # List swap partitions activated at boot time. + swapDevices = + [ # { device = "/dev/disk/by-label/swap"; } + ]; + + # Select internationalisation properties. + # i18n = { + # consoleFont = "lat9w-16"; + # consoleKeyMap = "us"; + # defaultLocale = "en_US.UTF-8"; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable the X11 windowing system. + # services.xserver.enable = true; + # services.xserver.layout = "us"; + # services.xserver.xkbOptions = "eurosign:e"; + + # Enable the KDE Desktop Environment. + # services.xserver.displayManager.kdm.enable = true; + # services.xserver.desktopManager.kde4.enable = true; +} +EOF + + exit 0 +fi; + +# This duplicates the work made below, but it is useful for processing +# the output of nixos-option with other tools such as nixos-gui. +if $xml; then + evalNix --xml --no-location <<EOF +let + reach = attrs: attrs${option:+.$option}; + nixos = import <nixos> {}; + nixpkgs = import <nixpkgs> {}; + sources = builtins.map (f: f.source); + opt = reach nixos.eval.options; + cfg = reach nixos.config; +in + +with nixpkgs.lib; + +let + optStrict = v: + let + traverse = x : + if isAttrs x then + if x ? outPath then true + else all id (mapAttrsFlatten (n: traverseNoAttrs) x) + else traverseNoAttrs x; + traverseNoAttrs = x: + # do not continue in attribute sets + if isAttrs x then true + else if isList x then all id (map traverse x) + else true; + in assert traverse v; v; +in + +if isOption opt then + optStrict ({} + // optionalAttrs (opt ? default) { inherit (opt) default; } + // optionalAttrs (opt ? example) { inherit (opt) example; } + // optionalAttrs (opt ? description) { inherit (opt) description; } + // optionalAttrs (opt ? type) { typename = opt.type.name; } + // optionalAttrs (opt ? options) { inherit (opt) options; } + // { + # to disambiguate the xml output. + _isOption = true; + declarations = sources opt.declarations; + definitions = sources opt.definitions; + value = cfg; + }) +else + opt +EOF + exit $? +fi + +if test "$(evalOpt "_type" 2> /dev/null)" = '"option"'; then + $value && evalCfg; + + if $desc; then + $value && echo; + + if default=$(evalOpt "default" - 2> /dev/null); then + echo "Default: $default" + else + echo "Default: <None>" + fi + if example=$(evalOpt "example" - 2> /dev/null); then + echo "Example: $example" + fi + echo "Description:" + eval printf $(evalOpt "description") + fi + + if $defs; then + $desc || $value && echo; + + printPath () { echo " $1"; } + + echo "Declared by:" + nixMap printPath "$(findSources "declarations")" + echo "" + echo "Defined by:" + nixMap printPath "$(findSources "definitions")" + echo "" + fi + +else + # echo 1>&2 "Warning: This value is not an option." + + result=$(evalCfg) + if names=$(attrNames "$result" 2> /dev/null); then + echo 1>&2 "This attribute set contains:" + escapeQuotes () { eval echo "$1"; } + nixMap escapeQuotes "$names" + else + echo 1>&2 "An error occured while looking for attribute names." + echo $result + fi +fi diff --git a/nixos/modules/installer/tools/nixos-rebuild.sh b/nixos/modules/installer/tools/nixos-rebuild.sh new file mode 100644 index 000000000000..8734cb273d49 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-rebuild.sh @@ -0,0 +1,222 @@ +#! @shell@ -e + +showSyntax() { + # !!! more or less cut&paste from + # system/switch-to-configuration.sh (which we call, of course). + cat <<EOF +Usage: $0 [OPTIONS...] OPERATION + +The operation is one of the following: + + switch: make the configuration the boot default and activate now + boot: make the configuration the boot default + test: activate the configuration, but don't make it the boot default + build: build the configuration, but don't make it the default or + activate it + build-vm: build a virtual machine containing the configuration + (useful for testing) + build-vm-with-bootloader: + like build-vm, but include a boot loader in the VM + dry-run: just show what store paths would be built/downloaded + +Options: + + --upgrade fetch the latest version of NixOS before rebuilding + --install-grub (re-)install the Grub bootloader + --no-build-nix don't build the latest Nix from Nixpkgs before + building NixOS + --rollback restore the previous NixOS configuration (only + with switch, boot, test, build) + --profile-name / -p install in the specified system profile + --fast same as --no-build-nix --show-trace + +Various nix-build options are also accepted, in particular: + + --show-trace show a detailed stack trace for evaluation errors + +Environment variables affecting nixos-rebuild: + + \$NIX_PATH Nix expression search path + \$NIXOS_CONFIG path to the NixOS system configuration specification +EOF + exit 1 +} + + +# Parse the command line. +extraBuildFlags=() +action= +buildNix=1 +rollback= +upgrade= +repair= +profile=/nix/var/nix/profiles/system + +while [ "$#" -gt 0 ]; do + i="$1"; shift 1 + case "$i" in + --help) + showSyntax + ;; + switch|boot|test|build|dry-run|build-vm|build-vm-with-bootloader) + action="$i" + ;; + --install-grub) + export NIXOS_INSTALL_GRUB=1 + ;; + --no-build-nix) + buildNix= + ;; + --rollback) + rollback=1 + ;; + --upgrade) + upgrade=1 + ;; + --repair) + repair=1 + extraBuildFlags+=("$i") + ;; + --show-trace|--no-build-hook|--keep-failed|-K|--keep-going|-k|--verbose|-v|-vv|-vvv|-vvvv|-vvvvv|--fallback|--repair) + extraBuildFlags+=("$i") + ;; + --max-jobs|-j|--cores|-I) + j="$1"; shift 1 + extraBuildFlags+=("$i" "$j") + ;; + --option) + j="$1"; shift 1 + k="$1"; shift 1 + extraBuildFlags+=("$i" "$j" "$k") + ;; + --fast) + buildNix= + extraBuildFlags+=(--show-trace) + ;; + --profile-name|-p) + if [ -z "$1" ]; then + echo "$0: ‘--profile-name’ requires an argument" + exit 1 + fi + if [ "$1" != system ]; then + profile="/nix/var/nix/profiles/system-profiles/$1" + mkdir -p -m 0755 "$(dirname "$profile")" + fi + shift 1 + ;; + *) + echo "$0: unknown option \`$i'" + exit 1 + ;; + esac +done + +if [ -z "$action" ]; then showSyntax; fi + +if [ -n "$rollback" ]; then + buildNix= +fi + + +tmpDir=$(mktemp -t -d nixos-rebuild.XXXXXX) +trap 'rm -rf "$tmpDir"' EXIT + + +# If the Nix daemon is running, then use it. This allows us to use +# the latest Nix from Nixpkgs (below) for expression evaluation, while +# still using the old Nix (via the daemon) for actual store access. +# This matters if the new Nix in Nixpkgs has a schema change. It +# would upgrade the schema, which should only happen once we actually +# switch to the new configuration. +# If --repair is given, don't try to use the Nix daemon, because the +# flag can only be used directly. +if [ -z "$repair" ] && systemctl show nix-daemon.socket nix-daemon.service | grep -q ActiveState=active; then + export NIX_REMOTE=${NIX_REMOTE:-daemon} +fi + + +# If ‘--upgrade’ is given, run ‘nix-channel --update nixos’. +if [ -n "$upgrade" ]; then + nix-channel --update nixos +fi + + +# First build Nix, since NixOS may require a newer version than the +# current one. Of course, the same goes for Nixpkgs, but Nixpkgs is +# more conservative. +if [ "$action" != dry-run -a -n "$buildNix" ]; then + echo "building Nix..." >&2 + if ! nix-build '<nixos>' -A config.environment.nix -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then + if ! nix-build '<nixos>' -A nixFallback -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null; then + nix-build '<nixpkgs>' -A nixUnstable -o $tmpDir/nix "${extraBuildFlags[@]}" > /dev/null + fi + fi + PATH=$tmpDir/nix/bin:$PATH +fi + + +# Update the version suffix if we're building from Git (so that +# nixos-version shows something useful). +if nixos=$(nix-instantiate --find-file nixos "${extraBuildFlags[@]}"); then + suffix=$(@shell@ $nixos/modules/installer/tools/get-version-suffix "${extraBuildFlags[@]}") + if [ -n "$suffix" ]; then + echo -n "$suffix" > "$nixos/.version-suffix" || true + fi +fi + + +if [ "$action" = dry-run ]; then + extraBuildFlags+=(--dry-run) +fi + + +# Either upgrade the configuration in the system profile (for "switch" +# or "boot"), or just build it and create a symlink "result" in the +# current directory (for "build" and "test"). +if [ -z "$rollback" ]; then + echo "building the system configuration..." >&2 + if [ "$action" = switch -o "$action" = boot ]; then + nix-env "${extraBuildFlags[@]}" -p "$profile" -f '<nixos>' --set -A system + pathToConfig="$profile" + elif [ "$action" = test -o "$action" = build -o "$action" = dry-run ]; then + nix-build '<nixos>' -A system -K -k "${extraBuildFlags[@]}" > /dev/null + pathToConfig=./result + elif [ "$action" = build-vm ]; then + nix-build '<nixos>' -A vm -K -k "${extraBuildFlags[@]}" > /dev/null + pathToConfig=./result + elif [ "$action" = build-vm-with-bootloader ]; then + nix-build '<nixos>' -A vmWithBootLoader -K -k "${extraBuildFlags[@]}" > /dev/null + pathToConfig=./result + else + showSyntax + fi +else # [ -n "$rollback" ] + if [ "$action" = switch -o "$action" = boot ]; then + nix-env --rollback -p "$profile" + pathToConfig="$profile" + elif [ "$action" = test -o "$action" = build ]; then + systemNumber=$( + nix-env -p "$profile" --list-generations | + sed -n '/current/ {g; p;}; s/ *\([0-9]*\).*/\1/; h' + ) + ln -sT "$profile"-${systemNumber}-link ./result + pathToConfig=./result + else + showSyntax + fi +fi + + +# If we're not just building, then make the new configuration the boot +# default and/or activate it now. +if [ "$action" = switch -o "$action" = boot -o "$action" = test ]; then + $pathToConfig/bin/switch-to-configuration "$action" +fi + + +if [ "$action" = build-vm ]; then + cat >&2 <<EOF + +Done. The virtual machine can be started by running $(echo $pathToConfig/bin/run-*-vm). +EOF +fi diff --git a/nixos/modules/installer/tools/nixos-version.sh b/nixos/modules/installer/tools/nixos-version.sh new file mode 100644 index 000000000000..5dbf277fe4c4 --- /dev/null +++ b/nixos/modules/installer/tools/nixos-version.sh @@ -0,0 +1,2 @@ +#! @shell@ +echo "@nixosVersion@ (@nixosCodeName@)" diff --git a/nixos/modules/installer/tools/tools.nix b/nixos/modules/installer/tools/tools.nix new file mode 100644 index 000000000000..c761d74a8902 --- /dev/null +++ b/nixos/modules/installer/tools/tools.nix @@ -0,0 +1,112 @@ +# This module generates nixos-install, nixos-rebuild, +# nixos-hardware-scan, etc. + +{ config, pkgs, modulesPath, ... }: + +let + ### implementation + cfg = config.installer; + + makeProg = args: pkgs.substituteAll (args // { + dir = "bin"; + isExecutable = true; + }); + + nixosBuildVMS = makeProg { + name = "nixos-build-vms"; + src = ./nixos-build-vms/nixos-build-vms.sh; + }; + + nixosInstall = makeProg { + name = "nixos-install"; + src = ./nixos-install.sh; + + inherit (pkgs) perl pathsFromGraph; + nix = config.environment.nix; + + nixClosure = pkgs.runCommand "closure" + { exportReferencesGraph = ["refs" config.environment.nix]; } + "cp refs $out"; + }; + + nixosRebuild = makeProg { + name = "nixos-rebuild"; + src = ./nixos-rebuild.sh; + }; + + /* + nixosGenSeccureKeys = makeProg { + name = "nixos-gen-seccure-keys"; + src = ./nixos-gen-seccure-keys.sh; + }; + */ + + nixosHardwareScan = makeProg { + name = "nixos-hardware-scan"; + src = ./nixos-hardware-scan.pl; + inherit (pkgs) perl dmidecode; + }; + + nixosOption = makeProg { + name = "nixos-option"; + src = ./nixos-option.sh; + }; + + nixosVersion = makeProg { + name = "nixos-version"; + src = ./nixos-version.sh; + inherit (config.system) nixosVersion nixosCodeName; + }; + + nixosGui = pkgs.xulrunnerWrapper { + launcher = "nixos-gui"; + application = pkgs.stdenv.mkDerivation { + name = "nixos-gui"; + buildCommand = '' + cp -r "$gui" "$out" + + # Do not force the copy if the file exists in the sources (this + # happens for developpers) + test -e "$out/chrome/content/jquery-1.5.2.js" || + cp -f "$jquery" "$out/chrome/content/jquery-1.5.2.js" + ''; + gui = pkgs.lib.cleanSource "${modulesPath}/../gui"; + jquery = pkgs.fetchurl { + url = http://code.jquery.com/jquery-1.5.2.min.js; + sha256 = "8f0a19ee8c606b35a10904951e0a27da1896eafe33c6e88cb7bcbe455f05a24a"; + }; + }; + }; + +in + +{ + options = { + + installer.enableGraphicalTools = pkgs.lib.mkOption { + default = false; + type = with pkgs.lib.types; bool; + example = true; + description = '' + Enable the installation of graphical tools. + ''; + }; + + }; + + config = { + environment.systemPackages = + [ nixosBuildVMS + nixosInstall + nixosRebuild + nixosHardwareScan + #nixosGenSeccureKeys + nixosOption + nixosVersion + ] ++ pkgs.lib.optional cfg.enableGraphicalTools nixosGui; + + system.build = { + inherit nixosInstall nixosHardwareScan nixosOption; + }; + }; +} |