diff --git a/doc/manual/default.nix b/doc/manual/default.nix index c82a46b0537..d3f554c099e 100644 --- a/doc/manual/default.nix +++ b/doc/manual/default.nix @@ -57,12 +57,14 @@ in rec { ${pkgs.docbook5_xsl}/xml/xsl/docbook/xhtml/docbook.xsl \ ./manual.xml - ln -s ${pkgs.docbook5_xsl}/xml/xsl/docbook/images $dst/ + mkdir -p $dst/images/callouts + cp ${pkgs.docbook5_xsl}/xml/xsl/docbook/images/callouts/*.gif $dst/images/callouts/ + cp ${./style.css} $dst/style.css ensureDir $out/nix-support echo "doc manual $dst manual.html" >> $out/nix-support/hydra-build-products - ''; + ''; # */ }; # Generate the NixOS manpages. diff --git a/doc/manual/man-nixos-rebuild.xml b/doc/manual/man-nixos-rebuild.xml index 383334d82e1..ddf4e40be0c 100644 --- a/doc/manual/man-nixos-rebuild.xml +++ b/doc/manual/man-nixos-rebuild.xml @@ -281,7 +281,7 @@ the Nix manual for details. - /var/run/current-system + /run/current-system A symlink to the currently active system configuration in the Nix store. diff --git a/doc/manual/userconfiguration.xml b/doc/manual/userconfiguration.xml index 2cad256c742..7c6540caf3a 100644 --- a/doc/manual/userconfiguration.xml +++ b/doc/manual/userconfiguration.xml @@ -13,20 +13,20 @@ them found both by Compiz and by Compiz Configuration Settings (also in Compiz Fusion distribution). By default they look in Compiz installation path and in home directory. You do not need to track /nix/store manually - everything is already in - /var/run/current-system/sw/share. + /run/current-system/sw/share. $HOME/.compiz/plugins should contain plugins you want to load. All the installed plugins are available in - /var/run/current-system/sw/share/compiz-plugins/compiz/, + /run/current-system/sw/share/compiz-plugins/compiz/, so you can use symlinks to this directory. $HOME/.compiz/metadata should contain metadata (definition of configuration options) for plugins you want to load. All the installed metadata is available in - /var/run/current-system/sw/share/compiz/, + /run/current-system/sw/share/compiz/, so you can use symlinks to this directory. @@ -35,16 +35,16 @@ should be found, but if you run Compiz with GConf configuration (default for X server job for now), you have to link - /var/run/current-system/sw/share/compizconfig/backends/ + /run/current-system/sw/share/compizconfig/backends/ into $HOME/.compizconfig/backends directory. To summarize the above, these are the commands you have to execute - ln -s /var/run/current-system/sw/share/compiz/ $HOME/.compiz/metadata - ln -s /var/run/current-system/sw/share/compiz-plugins/compiz/ $HOME/.compiz/plugins - ln -s /var/run/current-system/sw/share/compizconfig/backends/ $HOME/.compizconfig/backends + ln -s /run/current-system/sw/share/compiz/ $HOME/.compiz/metadata + ln -s /run/current-system/sw/share/compiz-plugins/compiz/ $HOME/.compiz/plugins + ln -s /run/current-system/sw/share/compizconfig/backends/ $HOME/.compizconfig/backends Now you can launch ccsm and configure everything. You should select GConf as a backend in the preferences menu of ccsm @@ -57,7 +57,7 @@ To have pidgin-latex plugin working after installation, you need the following: - Symlink /var/run/current-system/sw/share/pidgin-latex/pidgin-latex.so + Symlink /run/current-system/sw/share/pidgin-latex/pidgin-latex.so to $HOME/.purple/plugins/pidgin-latex.so diff --git a/gui/chrome/content/nixos.js b/gui/chrome/content/nixos.js index 7b45b6c006a..63a3c16a573 100644 --- a/gui/chrome/content/nixos.js +++ b/gui/chrome/content/nixos.js @@ -21,8 +21,8 @@ NixOS.prototype = { nixos: "/etc/nixos/nixos", nixpkgs: "/etc/nixos/nixpkgs", config: "/etc/nixos/configuration.nix", - instantiateBin: "/var/run/current-system/sw/bin/nix-instantiate", - optionBin: "/var/run/current-system/sw/bin/nixos-option", + instantiateBin: "/run/current-system/sw/bin/nix-instantiate", + optionBin: "/run/current-system/sw/bin/nixos-option", tmpFile: "nixos-gui", option: null }; diff --git a/lib/test-driver/Machine.pm b/lib/test-driver/Machine.pm index f0d5fbc19ea..c501aa5f1ed 100644 --- a/lib/test-driver/Machine.pm +++ b/lib/test-driver/Machine.pm @@ -29,7 +29,8 @@ sub new { $startCommand = "qemu-kvm -m 384 " . "-net nic,model=virtio \$QEMU_OPTS "; - $startCommand .= "-drive file=" . Cwd::abs_path($args->{hda}) . ",if=virtio,boot=on,werror=report " + my $iface = $args->{hdaInterface} || "virtio"; + $startCommand .= "-drive file=" . Cwd::abs_path($args->{hda}) . ",if=$iface,boot=on,werror=report " if defined $args->{hda}; $startCommand .= "-cdrom $args->{cdrom} " if defined $args->{cdrom}; diff --git a/lib/test-driver/test-driver.pl b/lib/test-driver/test-driver.pl index fc4b7ea0555..c6a707cdf6b 100644 --- a/lib/test-driver/test-driver.pl +++ b/lib/test-driver/test-driver.pl @@ -135,7 +135,7 @@ sub runTests { # Figure out where to put the *.gcda files so that the # report generator can find the corresponding kernel # sources. - my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /var/run/current-system/kernel))/.build/linux-*"); + my $kernelDir = $vm->mustSucceed("echo \$(dirname \$(readlink -f /run/current-system/kernel))/.build/linux-*"); chomp $kernelDir; my $coverageDir = "/tmp/xchg/coverage-data/$kernelDir"; diff --git a/maintainers/scripts/ec2/create-ebs-amis.py b/maintainers/scripts/ec2/create-ebs-amis.py index 0afa6d564e3..939bd30942d 100755 --- a/maintainers/scripts/ec2/create-ebs-amis.py +++ b/maintainers/scripts/ec2/create-ebs-amis.py @@ -33,6 +33,7 @@ f.write('''{{ f.close() depl = deployment.Deployment("./ebs-creator.json", create=True, nix_exprs=["./ebs-creator.nix", "./ebs-creator-config.nix"]) +depl.load_state() if not args.keep: depl.destroy_vms() depl.deploy() @@ -163,6 +164,7 @@ f.write( f.close() test_depl = deployment.Deployment("./ebs-test.json", create=True, nix_exprs=["./ebs-test.nix"]) +test_depl.load_state() test_depl.deploy(create_only=True) test_depl.machines['machine'].run_command("nixos-version") if not args.keep: test_depl.destroy_vms() diff --git a/modules/installer/cd-dvd/iso-image.nix b/modules/installer/cd-dvd/iso-image.nix index c1094daa49f..4f87f29f2e9 100644 --- a/modules/installer/cd-dvd/iso-image.nix +++ b/modules/installer/cd-dvd/iso-image.nix @@ -168,7 +168,6 @@ in boot.loader.grub.enable = false; # !!! Hack - attributes expected by other modules. - system.build.menuBuilder = "true"; system.boot.loader.kernelFile = "bzImage"; environment.systemPackages = [ pkgs.grub2 ]; diff --git a/modules/installer/cd-dvd/system-tarball-fuloong2f.nix b/modules/installer/cd-dvd/system-tarball-fuloong2f.nix index 5a23a394f7f..5b6e0036639 100644 --- a/modules/installer/cd-dvd/system-tarball-fuloong2f.nix +++ b/modules/installer/cd-dvd/system-tarball-fuloong2f.nix @@ -170,9 +170,6 @@ in boot.loader.generationsDir.enable = false; system.boot.loader.kernelFile = "vmlinux"; - # Needed for nixos to evaluate - system.build.menuBuilder = "true"; - nixpkgs.config = { platform = pkgs.platforms.fuloong2f_n32; }; diff --git a/modules/installer/cd-dvd/system-tarball-sheevaplug.nix b/modules/installer/cd-dvd/system-tarball-sheevaplug.nix index 24e7a006314..f53079ecd9b 100644 --- a/modules/installer/cd-dvd/system-tarball-sheevaplug.nix +++ b/modules/installer/cd-dvd/system-tarball-sheevaplug.nix @@ -177,9 +177,6 @@ in services.ttyBackgrounds.enable = false; jobs.openssh.startOn = pkgs.lib.mkOverrideTemplate 50 {} ""; - # Needed for nixos to evaluate - system.build.menuBuilder = "true"; - nixpkgs.config = { platform = pkgs.platforms.sheevaplug; }; diff --git a/modules/installer/grub/grub-menu-builder.sh b/modules/installer/grub/grub-menu-builder.sh deleted file mode 100644 index f0e9fdb288c..00000000000 --- a/modules/installer/grub/grub-menu-builder.sh +++ /dev/null @@ -1,305 +0,0 @@ -#! @bash@/bin/sh -e - -shopt -s nullglob - -export PATH=/empty -for i in @path@; do PATH=$PATH:$i/bin; done - -if test $# -ne 1; then - echo "Usage: grub-menu-builder.sh DEFAULT-CONFIG" - exit 1 -fi - -grubVersion="@version@" -defaultConfig="$1" - -case "$grubVersion" in - 1|2) - echo "updating GRUB $grubVersion menu..." - ;; - *) - echo "Unsupported GRUB version \`$grubVersion'" >&2 - echo "Supported versions are \`1' (GRUB Legacy) and \`2' (GRUB 1.9x)." >&2 - exit 1 - ;; -esac - - -# Discover whether /boot is on the same filesystem as / and -# /nix/store. If not, then all kernels and initrds must be copied to -# /boot, and all paths in the GRUB config file must be relative to the -# root of the /boot filesystem. `$bootRoot' is the path to be -# prepended to paths under /boot. -if [ "$(stat -c '%D' /.)" != "$(stat -c '%D' /boot/.)" ]; then - bootRoot= - copyKernels=1 -elif [ "$(stat -c '%D' /boot/.)" != "$(stat -c '%D' /nix/store/.)" ]; then - bootRoot=/boot - copyKernels=1 -else - bootRoot=/boot - copyKernels="@copyKernels@" # user can override in the NixOS config -fi - - -prologue() { - case "$grubVersion" in - 1) - cat > "$1" << GRUBEND -# Automatically generated. DO NOT EDIT THIS FILE! -default @default@ -timeout @timeout@ -GRUBEND - if [ -n "@splashImage@" ]; then - cp -f "@splashImage@" /boot/background.xpm.gz - echo "splashimage $bootRoot/background.xpm.gz" >> "$1" - fi - ;; - 2) - cp -f @grub@/share/grub/unicode.pf2 /boot/grub/unicode.pf2 - cat > "$1" <> "$1" <-/file to --. -cleanName() { - local path="$1" - echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g' -} - - -# Copy a file from the Nix store to /boot/kernels. -declare -A filesCopied - -copyToKernelsDir() { - local src="$1" - local p="kernels/$(cleanName $src)" - local dst="/boot/$p" - # Don't copy the file if $dst already exists. This means that we - # have to create $dst atomically to prevent partially copied - # kernels or initrd if this script is ever interrupted. - if ! test -e $dst; then - local dstTmp=$dst.tmp.$$ - cp "$src" "$dstTmp" - mv $dstTmp $dst - fi - filesCopied[$dst]=1 - result="$bootRoot/$p" -} - - -# Add an entry for a configuration to the Grub menu, and if -# appropriate, copy its kernel and initrd to /boot/kernels. -addEntry() { - local name="$1" - local path="$2" - local shortSuffix="$3" - - configurationCounter=$((configurationCounter + 1)) - if test $configurationCounter -gt @configurationLimit@; then - return - fi - - if ! test -e $path/kernel -a -e $path/initrd; then - return - fi - - local kernel=$(readlink -f $path/kernel) - local initrd=$(readlink -f $path/initrd) - local xen=$([ -f $path/xen.gz ] && readlink -f $path/xen.gz) - - if test "$path" = "$defaultConfig"; then - cp "$kernel" /boot/nixos-kernel - cp "$initrd" /boot/nixos-initrd - cp "$(readlink -f "$path/init")" /boot/nixos-init - case "$grubVersion" in - 1) - cat > /boot/nixos-grub-config < /boot/nixos-grub-config </dev/null || true) - if test -n "$confName"; then - name="$confName $3" - fi - - local kernelParams="systemConfig=$(readlink -f $path) init=$(readlink -f $path/init) $(cat $path/kernel-params)" - local xenParams="$([ -n "$xen" ] && cat $path/xen-params)" - - case "$grubVersion" in - 1) - cat >> "$tmp" << GRUBEND -title $name - @extraPerEntryConfig@ - ${xen:+kernel $xen $xenParams} - $(if [ -z "$xen" ]; then echo kernel; else echo module; fi) $kernel $kernelParams - $(if [ -z "$xen" ]; then echo initrd; else echo module; fi) $initrd -GRUBEND - ;; - 2) - cat >> "$tmp" << GRUBEND -menuentry "$name" { - @extraPerEntryConfig@ - ${xen:+multiboot $xen $xenParams} - $(if [ -z "$xen" ]; then echo linux; else echo module; fi) $kernel $kernelParams - $(if [ -z "$xen" ]; then echo initrd; else echo module; fi) $initrd -} -GRUBEND - ;; - esac -} - - -if test -n "$copyKernels"; then - mkdir -p /boot/kernels -fi - -@extraPrepareConfig@ - -# Additional entries specified verbatim by the configuration. -extraEntries=`cat <> $tmp <> $tmp -fi - -addEntry "NixOS - Default" $defaultConfig "" - -if test -z "@extraEntriesBeforeNixOS@"; then - echo "$extraEntries" >> $tmp -fi - -# Add all generations of the system profile to the menu, in reverse -# (most recent to least recent) order. -for link in $((ls -d $defaultConfig/fine-tune/* ) | sort -n); do - date=$(stat --printf="%y\n" $link | sed 's/\..*//') - addEntry "NixOS - variation" $link "" -done - -if [ "$grubVersion" = 2 ]; then - cat >> $tmp <> $tmp < /var/lib/gogoc/gogoc.conf + ''; + script = "cd /var/lib/gogoc; exec gogoc -y -f ./gogoc.conf"; path = [pkgs.gogoclient]; }; - system.activationScripts.gogoClientConf = '' - mkdir -p /var/lib/gogoc - chmod 700 /var/lib/gogoc - install -m400 ${pkgs.gogoclient}/share/${pkgs.gogoclient.name}/gogoc.conf.sample /etc/gogoc.conf.default - ${pkgs.gnused}/bin/sed -i -e "s|^userid=|&${cfg.username}|" /etc/gogoc.conf.default - ${pkgs.gnused}/bin/sed -i -e "s|^passwd=|&${if cfg.password == "" then "" else "$(cat ${cfg.password})"}|" /etc/gogoc.conf.default - ${pkgs.gnused}/bin/sed -i -e "s|^server=.*|server=${cfg.server}|" /etc/gogoc.conf.default - ${pkgs.gnused}/bin/sed -i -e "s|^auth_method=.*|auth_method=${if cfg.password == "" then "anonymous" else "any"}|" /etc/gogoc.conf.default - ${pkgs.gnused}/bin/sed -i -e "s|^#log_file=|log_file=1|" /etc/gogoc.conf.default - mv /etc/gogoc.conf.default /etc/gogoc.conf - ''; }; } diff --git a/modules/services/security/clamav.nix b/modules/services/security/clamav.nix new file mode 100644 index 00000000000..5ccb4927fcb --- /dev/null +++ b/modules/services/security/clamav.nix @@ -0,0 +1,80 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + clamavUser = "clamav"; + stateDir = "/var/lib/clamav"; + clamavGroup = clamavUser; + cfg = config.services.clamav; +in +{ + ###### interface + + options = { + + services.clamav = { + updater = { + enable = mkOption { + default = false; + description = '' + Whether to enable automatic ClamAV virus definitions database updates. + ''; + }; + + frequency = mkOption { + default = 12; + description = '' + Number of database checks per day. + ''; + }; + + config = mkOption { + default = ""; + description = '' + Extra configuration for freshclam. Contents will be added verbatim to the + configuration file. + ''; + }; + }; + }; + }; + + ###### implementation + + config = mkIf cfg.updater.enable { + environment.systemPackages = [ pkgs.clamav ]; + users.extraUsers = singleton + { name = clamavUser; + uid = config.ids.uids.clamav; + description = "ClamAV daemon user"; + home = stateDir; + }; + + users.extraGroups = singleton + { name = clamavGroup; + gid = config.ids.gids.clamav; + }; + + services.clamav.updater.config = '' + DatabaseDirectory ${stateDir} + Foreground yes + Checks ${toString cfg.updater.frequency} + DatabaseMirror database.clamav.net + ''; + + jobs = { + clamav_updater = { + name = "clamav-updater"; + startOn = "started network-interfaces"; + stopOn = "stopping network-interfaces"; + + preStart = '' + mkdir -m 0755 -p ${stateDir} + chown ${clamavUser}:${clamavGroup} ${stateDir} + ''; + exec = "${pkgs.clamav}/bin/freshclam --config-file=${pkgs.writeText "freshclam.conf" cfg.updater.config}"; + }; + }; + + }; + +} \ No newline at end of file diff --git a/modules/services/security/fprot.nix b/modules/services/security/fprot.nix new file mode 100644 index 00000000000..9f1fc4ed6d8 --- /dev/null +++ b/modules/services/security/fprot.nix @@ -0,0 +1,88 @@ +{ config, pkgs, ... }: +with pkgs.lib; +let + fprotUser = "fprot"; + stateDir = "/var/lib/fprot"; + fprotGroup = fprotUser; + cfg = config.services.fprot; +in { + options = { + + services.fprot = { + updater = { + enable = mkOption { + default = false; + description = '' + Whether to enable automatic F-Prot virus definitions database updates. + ''; + }; + + productData = mkOption { + default = "${pkgs.fprot}/opt/f-prot/product.data"; + description = '' + product.data file. Defaults to the one supplied with installation package. + ''; + }; + + frequency = mkOption { + default = 30; + description = '' + Update virus definitions every X minutes. + ''; + }; + + licenseKeyfile = mkOption { + default = "${pkgs.fprot}/opt/f-prot/license.key"; + description = '' + License keyfile. Defaults to the one supplied with installation package. + ''; + }; + + }; + }; + }; + + ###### implementation + + config = mkIf cfg.updater.enable { + environment.systemPackages = [ pkgs.fprot ]; + environment.etc = singleton { + source = "${pkgs.fprot}/opt/f-prot/f-prot.conf"; + target = "f-prot.conf"; + }; + + users.extraUsers = singleton + { name = fprotUser; + uid = config.ids.uids.fprot; + description = "F-Prot daemon user"; + home = stateDir; + }; + + users.extraGroups = singleton + { name = fprotGroup; + gid = config.ids.gids.fprot; + }; + + services.cron.systemCronJobs = [ "*/${toString cfg.updater.frequency} * * * * root start fprot-updater" ]; + + jobs = { + fprot_updater = { + name = "fprot-updater"; + task = true; + + # have to copy fpupdate executable because it insists on storing the virus database in the same dir + preStart = '' + mkdir -m 0755 -p ${stateDir} + chown ${fprotUser}:${fprotGroup} ${stateDir} + cp ${pkgs.fprot}/opt/f-prot/fpupdate ${stateDir} + ln -sf ${cfg.updater.productData} ${stateDir}/product.data + ''; + #setuid = fprotUser; + #setgid = fprotGroup; + exec = "/var/lib/fprot/fpupdate --keyfile ${cfg.updater.licenseKeyfile}"; + }; + }; + + }; + +} \ No newline at end of file diff --git a/modules/services/system/cgroups.nix b/modules/services/system/cgroups.nix index 199d12268ce..5d5777909e9 100644 --- a/modules/services/system/cgroups.nix +++ b/modules/services/system/cgroups.nix @@ -37,14 +37,14 @@ in default = '' mount { - cpu = /dev/cgroup/cpu; + cpu = /sys/fs/cgroup/cpu; } ''; example = '' mount { - cpu = /dev/cgroup/cpu; - cpuacct = /dev/cgroup/cpuacct; + cpu = /sys/fs/cgroup/cpu; + cpuacct = /sys/fs/cgroup/cpuacct; } # Create a "www" cgroup with a lower share of the CPU (the @@ -105,10 +105,16 @@ in description = "Control groups daemon"; - path = [ pkgs.libcgroup pkgs.procps ]; + path = [ pkgs.libcgroup pkgs.procps pkgs.utillinux ]; preStart = '' + if [ -d /sys/fs/cgroup ]; then + if ! mountpoint -q /sys/fs/cgroup; then + mount -t tmpfs -o mode=755 /dev/cgroup /sys/fs/cgroup + fi + fi + cgclear || true # Mount the cgroup hierarchies. Note: we refer to the diff --git a/modules/services/web-servers/apache-httpd/default.nix b/modules/services/web-servers/apache-httpd/default.nix index ceb93cd8b01..2f90c515643 100644 --- a/modules/services/web-servers/apache-httpd/default.nix +++ b/modules/services/web-servers/apache-httpd/default.nix @@ -6,7 +6,9 @@ let mainCfg = config.services.httpd; - httpd = pkgs.apacheHttpd.override { mpm = mainCfg.multiProcessingModule; }; + httpd = mainCfg.package; + + httpdConf = mainCfg.configFile; php = pkgs.php.override { apacheHttpd = httpd; }; @@ -72,7 +74,7 @@ let phpOptions = ""; options = {}; }; - res = defaults // svcFunction { inherit config pkgs serverInfo; }; + res = defaults // svcFunction { inherit config pkgs serverInfo php; }; in res; in map f defs; @@ -280,7 +282,7 @@ let ''; - httpdConf = pkgs.writeText "httpd.conf" '' + confFile = pkgs.writeText "httpd.conf" '' ServerRoot ${httpd} @@ -403,10 +405,29 @@ in "; }; + package = mkOption { + default = pkgs.apacheHttpd.override { mpm = mainCfg.multiProcessingModule; }; + example = "pkgs.apacheHttpd_2_4"; + description = " + Overridable attribute of the Apache HTTP Server package to use. + "; + }; + + configFile = mkOption { + default = confFile; + example = ''pkgs.writeText "httpd.conf" "# my custom config file ...";''; + description = " + Overridable config file to use for Apache. By default, use the + file automatically generated by nixos. + "; + }; + extraConfig = mkOption { default = ""; description = " - These configuration lines will be passed verbatim to the apache config + These configuration lines will be appended to the Apache config + file. Note that this mechanism may not work when + is overridden. "; }; @@ -538,6 +559,7 @@ in users.extraUsers = singleton { name = mainCfg.user; + group = mainCfg.group; description = "Apache httpd user"; }; @@ -584,7 +606,7 @@ in preStart = '' mkdir -m 0750 -p ${mainCfg.stateDir} - chown root.wwwrun ${mainCfg.stateDir} + chown root.${mainCfg.group} ${mainCfg.stateDir} mkdir -m 0700 -p ${mainCfg.logDir} ${optionalString (mainCfg.documentRoot != null) diff --git a/modules/services/web-servers/apache-httpd/mediawiki.nix b/modules/services/web-servers/apache-httpd/mediawiki.nix index 9f321b173d3..2941c6d0d5a 100644 --- a/modules/services/web-servers/apache-httpd/mediawiki.nix +++ b/modules/services/web-servers/apache-httpd/mediawiki.nix @@ -1,4 +1,4 @@ -{ config, pkgs, serverInfo, ... }: +{ config, pkgs, serverInfo, php, ... }: with pkgs.lib; @@ -101,7 +101,7 @@ let '' ensureDir $out/bin for i in changePassword.php createAndPromote.php userOptions.php edit.php nukePage.php; do - makeWrapper ${pkgs.php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \ + makeWrapper ${php}/bin/php $out/bin/mediawiki-${config.id}-$(basename $i .php) \ --add-flags ${mediawikiRoot}/maintenance/$i done ''; diff --git a/modules/system/activation/switch-to-configuration.sh b/modules/system/activation/switch-to-configuration.sh index cc2f2e9282a..f52a310ea35 100644 --- a/modules/system/activation/switch-to-configuration.sh +++ b/modules/system/activation/switch-to-configuration.sh @@ -23,37 +23,7 @@ fi # Install or update the bootloader. if [ "$action" = "switch" -o "$action" = "boot" ]; then - - if [ "@bootLoader@" = "grub" ]; then - - mkdir -m 0700 -p /boot/grub - @menuBuilder@ @out@ - - # If the GRUB version has changed, then force a reinstall. - oldGrubVersion="$(cat /boot/grub/version 2>/dev/null || true)" - newGrubVersion="@grubVersion@" - - if [ "$NIXOS_INSTALL_GRUB" = 1 -o "$oldGrubVersion" != "$newGrubVersion" ]; then - for dev in @grubDevices@; do - if [ "$dev" != nodev ]; then - echo "installing the GRUB bootloader on $dev..." - @grub@/sbin/grub-install "$(readlink -f "$dev")" --no-floppy - fi - done - echo "$newGrubVersion" > /boot/grub/version - fi - - elif [ "@bootLoader@" = "generationsDir" ]; then - @menuBuilder@ @out@ - elif [ "@bootLoader@" = "efiBootStub" ]; then - @menuBuilder@ @out@ - else - echo "Warning: don't know how to make this configuration bootable; please enable a boot loader." 1>&2 - fi - - if [ -n "@initScriptBuilder@" ]; then - @initScriptBuilder@ @out@ - fi + @installBootLoader@ @out@ fi # Activate the new configuration. diff --git a/modules/system/activation/top-level.nix b/modules/system/activation/top-level.nix index e6c201ea2ba..923b91ad269 100644 --- a/modules/system/activation/top-level.nix +++ b/modules/system/activation/top-level.nix @@ -101,9 +101,6 @@ let ln -s ${kernelPath} $out/kernel ln -s ${config.system.modulesTree} $out/kernel-modules - if [ -n "$grub" ]; then - ln -s $grub $out/grub - fi ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd @@ -152,8 +149,9 @@ let inherit children; kernelParams = config.boot.kernelParams ++ config.boot.extraKernelParams; - menuBuilder = config.system.build.menuBuilder or "true"; - initScriptBuilder = config.system.build.initScriptBuilder; + installBootLoader = + config.system.build.installBootLoader + or "echo \"Warning: don't know how to make this configuration bootable; please enable a boot loader.\" 1>&2; true"; activationScript = config.system.activationScripts.script; nixosVersion = config.system.nixosVersion; @@ -161,11 +159,11 @@ let # Pass the names of all Upstart tasks to the activation script. tasks = attrValues (mapAttrs (n: v: if v.task then ["[${v.name}]=1"] else []) config.jobs); - + # Pass the names of all Upstart jobs that shouldn't be restarted # to the activation script. noRestartIfChanged = attrValues (mapAttrs (n: v: if v.restartIfChanged then [] else ["[${v.name}]=1"]) config.jobs); - + # Most of these are needed by grub-install. path = [ pkgs.coreutils @@ -176,20 +174,6 @@ let pkgs.systemd ]; - # Boot loaders - bootLoader = config.system.boot.loader.id; - grub = - if config.boot.loader.grub.enable - then config.system.build.grub - else null; - grubVersion = - if config.boot.loader.grub.enable - then (builtins.parseDrvName config.system.build.grub.name).version - else ""; - grubDevices = - let - wrapQuotes = s: "\"" + s + "\""; - in map wrapQuotes config.boot.loader.grub.devices; configurationName = config.boot.loader.grub.configurationName; }; diff --git a/modules/installer/efi-boot-stub/efi-boot-stub-builder.sh b/modules/system/boot/loader/efi-boot-stub/efi-boot-stub-builder.sh similarity index 100% rename from modules/installer/efi-boot-stub/efi-boot-stub-builder.sh rename to modules/system/boot/loader/efi-boot-stub/efi-boot-stub-builder.sh diff --git a/modules/installer/efi-boot-stub/efi-boot-stub.nix b/modules/system/boot/loader/efi-boot-stub/efi-boot-stub.nix similarity index 98% rename from modules/installer/efi-boot-stub/efi-boot-stub.nix rename to modules/system/boot/loader/efi-boot-stub/efi-boot-stub.nix index 1ca3cb0001e..a4e0ebd9845 100644 --- a/modules/installer/efi-boot-stub/efi-boot-stub.nix +++ b/modules/system/boot/loader/efi-boot-stub/efi-boot-stub.nix @@ -123,9 +123,7 @@ in system = mkIf (config.boot.loader.efiBootStub.enable && (assert (config.boot.kernelPackages.kernel.features ? efiBootStub && config.boot.kernelPackages.kernel.features.efiBootStub); true)) { - build = { - menuBuilder = efiBootStubBuilder; - }; + build.installBootLoader = efiBootStubBuilder; boot.loader.id = "efiBootStub"; boot.loader.kernelFile = platform.kernelTarget; }; diff --git a/modules/installer/generations-dir/generations-dir-builder.sh b/modules/system/boot/loader/generations-dir/generations-dir-builder.sh similarity index 100% rename from modules/installer/generations-dir/generations-dir-builder.sh rename to modules/system/boot/loader/generations-dir/generations-dir-builder.sh diff --git a/modules/installer/generations-dir/generations-dir.nix b/modules/system/boot/loader/generations-dir/generations-dir.nix similarity index 92% rename from modules/installer/generations-dir/generations-dir.nix rename to modules/system/boot/loader/generations-dir/generations-dir.nix index db9fa32c55a..8184b9c0a98 100644 --- a/modules/installer/generations-dir/generations-dir.nix +++ b/modules/system/boot/loader/generations-dir/generations-dir.nix @@ -19,7 +19,7 @@ let point to the current generation's kernel image, initial RAM disk, and other bootstrap files. - This optional is not necessary with bootloads such as GNU GRUB + This optional is not necessary with boot loaders such as GNU GRUB for which the menu is updated to point to the latest bootstrap files. However, it is needed for U-Boot on platforms where the boot command line is stored in flash memory rather than in a @@ -63,9 +63,7 @@ in ]; system = mkIf config.boot.loader.generationsDir.enable { - build = { - menuBuilder = generationsDirBuilder; - }; + build.installBootLoader = generationsDirBuilder; boot.loader.id = "generationsDir"; boot.loader.kernelFile = platform.kernelTarget; }; diff --git a/modules/installer/grub/grub.nix b/modules/system/boot/loader/grub/grub.nix similarity index 88% rename from modules/installer/grub/grub.nix rename to modules/system/boot/loader/grub/grub.nix index 94522c3c059..0a9b374cc60 100644 --- a/modules/installer/grub/grub.nix +++ b/modules/system/boot/loader/grub/grub.nix @@ -8,16 +8,17 @@ let grub = if cfg.version == 1 then pkgs.grub else pkgs.grub2; - grubMenuBuilder = pkgs.substituteAll { - src = ./grub-menu-builder.sh; - isExecutable = true; - inherit grub; - inherit (pkgs) bash; - path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep]; - inherit (config.boot.loader.grub) copyKernels extraPrepareConfig - extraConfig extraEntries extraEntriesBeforeNixOS extraPerEntryConfig - splashImage configurationLimit version default timeout; - }; + f = x: if x == null then "" else "" + x; + + grubConfig = pkgs.writeText "grub-config.xml" (builtins.toXML + { splashImage = f config.boot.loader.grub.splashImage; + grub = f grub; + fullVersion = (builtins.parseDrvName config.system.build.grub.name).version; + inherit (config.boot.loader.grub) + version extraConfig extraPerEntryConfig extraEntries + extraEntriesBeforeNixOS configurationLimit copyKernels timeout + default devices; + }); in @@ -199,7 +200,9 @@ in system.build = mkAssert (cfg.devices != []) "You must set the ‘boot.loader.grub.device’ option to make the system bootable." - { menuBuilder = grubMenuBuilder; + { installBootLoader = + "PERL5LIB=${makePerlPath [ pkgs.perlPackages.XMLLibXML pkgs.perlPackages.XMLSAX ]} " + + "${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig}"; inherit grub; }; diff --git a/modules/system/boot/loader/grub/install-grub.pl b/modules/system/boot/loader/grub/install-grub.pl new file mode 100644 index 00000000000..5e9f3b4efda --- /dev/null +++ b/modules/system/boot/loader/grub/install-grub.pl @@ -0,0 +1,242 @@ +use strict; +use warnings; +use XML::LibXML; +use File::Basename; +use File::Path; +use File::stat; +use File::Copy; +use POSIX; +use Cwd; + +my $defaultConfig = $ARGV[1] or die; + +my $dom = XML::LibXML->load_xml(location => $ARGV[0]); + +sub get { my ($name) = @_; return $dom->findvalue("/expr/attrs/attr[\@name = '$name']/*/\@value"); } + +sub readFile { + my ($fn) = @_; local $/ = undef; + open FILE, "<$fn" or return undef; my $s = ; close FILE; + local $/ = "\n"; chomp $s; return $s; +} + +sub writeFile { + my ($fn, $s) = @_; + open FILE, ">$fn" or die "cannot create $fn: $!\n"; + print FILE $s or die; + close FILE or die; +} + +my $grub = get("grub"); +my $grubVersion = int(get("version")); +my $extraConfig = get("extraConfig"); +my $extraPerEntryConfig = get("extraPerEntryConfig"); +my $extraEntries = get("extraEntries"); +my $extraEntriesBeforeNixOS = get("extraEntriesBeforeNixOS") eq "true"; +my $splashImage = get("splashImage"); +my $configurationLimit = int(get("configurationLimit")); +my $copyKernels = get("copyKernels") eq "true"; +my $timeout = int(get("timeout")); +my $defaultEntry = int(get("default")); + +die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2; + +print STDERR "updating GRUB $grubVersion menu...\n"; + +mkpath("/boot/grub", 0, 0700); + + +# Discover whether /boot is on the same filesystem as / and +# /nix/store. If not, then all kernels and initrds must be copied to +# /boot, and all paths in the GRUB config file must be relative to the +# root of the /boot filesystem. `$bootRoot' is the path to be +# prepended to paths under /boot. +my $bootRoot = "/boot"; +if (stat("/")->dev != stat("/boot")->dev) { + $bootRoot = ""; + $copyKernels = 1; +} elsif (stat("/boot")->dev != stat("/nix/store")->dev) { + $copyKernels = 1; +} + + +# Generate the header. +my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n"; + +if ($grubVersion == 1) { + $conf .= " + default $defaultEntry + timeout $timeout + "; + if ($splashImage) { + copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n"; + $conf .= "splashimage $bootRoot/background.xpm.gz\n"; + } +} + +else { + $conf .= " + if [ -s \$prefix/grubenv ]; then + load_env + fi + + # ‘grub-reboot’ sets a one-time saved entry, which we process here and + # then delete. + if [ \"\${saved_entry}\" ]; then + # The next line *has* to look exactly like this, otherwise KDM's + # reboot feature won't work properly with GRUB 2. + set default=\"\${saved_entry}\" + set saved_entry= + set prev_saved_entry= + save_env saved_entry + save_env prev_saved_entry + set timeout=1 + else + set default=$defaultEntry + set timeout=$timeout + fi + + if loadfont $bootRoot/grub/fonts/unicode.pf2; then + set gfxmode=640x480 + insmod gfxterm + insmod vbe + terminal_output gfxterm + fi + "; + + if ($splashImage) { + # FIXME: GRUB 1.97 doesn't resize the background image if it + # doesn't match the video resolution. + copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n"; + $conf .= " + insmod png + if background_image $bootRoot/background.png; then + set color_normal=white/black + set color_highlight=black/white + else + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + "; + } +} + +$conf .= "$extraConfig\n"; + + +# Generate the menu entries. +$conf .= "\n"; + +my %copied; +mkpath("/boot/kernels", 0, 0755) if $copyKernels; + +sub copyToKernelsDir { + my ($path) = @_; + return $path unless $copyKernels; + $path =~ /\/nix\/store\/(.*)/ or die; + my $name = $1; $name =~ s/\//-/g; + my $dst = "/boot/kernels/$name"; + # Don't copy the file if $dst already exists. This means that we + # have to create $dst atomically to prevent partially copied + # kernels or initrd if this script is ever interrupted. + if (! -e $dst) { + my $tmp = "$dst.tmp"; + copy $path, $tmp or die "cannot copy $path to $tmp\n"; + rename $tmp, $dst or die "cannot rename $tmp to $dst\n"; + } + $copied{$dst} = 1; + return "$bootRoot/kernels/$name"; +} + +sub addEntry { + my ($name, $path) = @_; + return unless -e "$path/kernel" && -e "$path/initrd"; + + my $kernel = copyToKernelsDir(Cwd::abs_path("$path/kernel")); + my $initrd = copyToKernelsDir(Cwd::abs_path("$path/initrd")); + my $xen = -e "$path/xen.gz" ? copyToKernelsDir(Cwd::abs_path("$path/xen.gz")) : undef; + + # FIXME: $confName + + my $kernelParams = + "systemConfig=" . Cwd::abs_path($path) . " " . + "init=" . Cwd::abs_path("$path/init") . " " . + readFile("$path/kernel-params"); + my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; + + if ($grubVersion == 1) { + $conf .= "title $name\n"; + $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; + $conf .= " kernel $xen $xenParams\n" if $xen; + $conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n"; + $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n"; + } else { + $conf .= "menuentry \"$name\" {\n"; + $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; + $conf .= " multiboot $xen $xenParams\n" if $xen; + $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n"; + $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; + $conf .= "}\n\n"; + } +} + + +# Add default entries. +$conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS; + +addEntry("NixOS - Default", $defaultConfig); + +$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS; + + +# Add entries for all previous generations of the system profile. +$conf .= "submenu \"NixOS - Old configurations\" {\n" if $grubVersion == 2; + +sub nrFromGen { my ($x) = @_; $x =~ /system-(.*)-link/; return $1; } + +my @links = sort + { nrFromGen($b) <=> nrFromGen($a) } + (glob "/nix/var/nix/profiles/system-*-link"); + +my $curEntry = 0; +foreach my $link (@links) { + last if $curEntry++ >= $configurationLimit; + my $date = strftime("%F", localtime(lstat($link)->mtime)); + my $version = + -e "$link/nixos-version" + ? readFile("$link/nixos-version") + : basename((glob(dirname(Cwd::abs_path("$link/kernel")) . "/lib/modules/*"))[0]); + addEntry("NixOS - Configuration " . nrFromGen($link) . " ($date - $version)", $link); +} + +$conf .= "}\n" if $grubVersion == 2; + + +# Atomically update the GRUB config. +my $confFile = $grubVersion == 1 ? "/boot/grub/menu.lst" : "/boot/grub/grub.cfg"; +my $tmpFile = $confFile . ".tmp"; +writeFile($tmpFile, $conf); +rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n"; + + +# Remove obsolete files from /boot/kernels. +foreach my $fn (glob "/boot/kernels/*") { + next if defined $copied{$fn}; + print STDERR "removing obsolete file $fn\n"; + unlink $fn; +} + + +# Install GRUB if the version changed from the last time we installed +# it. FIXME: shouldn't we reinstall if ‘devices’ changed? +my $prevVersion = readFile("/boot/grub/version") // ""; +if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1" || get("fullVersion") ne $prevVersion) { + foreach my $dev ($dom->findnodes('/expr/attrs/attr[@name = "devices"]/list/string/@value')) { + $dev = $dev->findvalue(".") or die; + next if $dev eq "nodev"; + print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n"; + system("$grub/sbin/grub-install", "--recheck", Cwd::abs_path($dev)) == 0 + or die "$0: installation of GRUB on $dev failed\n"; + } + writeFile("/boot/grub/version", get("fullVersion")); +} diff --git a/modules/installer/grub/memtest.nix b/modules/system/boot/loader/grub/memtest.nix similarity index 100% rename from modules/installer/grub/memtest.nix rename to modules/system/boot/loader/grub/memtest.nix diff --git a/modules/installer/grub/winkler-gnu-blue-640x480.png b/modules/system/boot/loader/grub/winkler-gnu-blue-640x480.png similarity index 100% rename from modules/installer/grub/winkler-gnu-blue-640x480.png rename to modules/system/boot/loader/grub/winkler-gnu-blue-640x480.png diff --git a/modules/installer/grub/winkler-gnu-blue.README b/modules/system/boot/loader/grub/winkler-gnu-blue.README similarity index 100% rename from modules/installer/grub/winkler-gnu-blue.README rename to modules/system/boot/loader/grub/winkler-gnu-blue.README diff --git a/modules/installer/init-script/init-script-builder.sh b/modules/system/boot/loader/init-script/init-script-builder.sh similarity index 95% rename from modules/installer/init-script/init-script-builder.sh rename to modules/system/boot/loader/init-script/init-script-builder.sh index 24128ae9abc..502b3b63af2 100644 --- a/modules/installer/init-script/init-script-builder.sh +++ b/modules/system/boot/loader/init-script/init-script-builder.sh @@ -1,4 +1,3 @@ - #! @bash@/bin/sh -e shopt -s nullglob @@ -7,7 +6,7 @@ export PATH=/empty for i in @path@; do PATH=$PATH:$i/bin; done if test $# -ne 1; then - echo "Usage: grub-menu-builder.sh DEFAULT-CONFIG" + echo "Usage: init-script-builder.sh DEFAULT-CONFIG" exit 1 fi @@ -44,7 +43,7 @@ addEntry() { configurationCounter=$((configurationCounter + 1)) - local stage2=$(readlink $path/init) + local stage2=$path/init content="$( echo "#!/bin/sh" diff --git a/modules/installer/init-script/init-script.nix b/modules/system/boot/loader/init-script/init-script.nix similarity index 87% rename from modules/installer/init-script/init-script.nix rename to modules/system/boot/loader/init-script/init-script.nix index edf7d23d2a7..ef5e97eb2c9 100644 --- a/modules/installer/init-script/init-script.nix +++ b/modules/system/boot/loader/init-script/init-script.nix @@ -41,10 +41,9 @@ in ###### implementation - config = { + config = mkIf config.boot.loader.initScript.enable { - system.build.initScriptBuilder = - if config.boot.loader.initScript.enable then initScriptBuilder else ""; + system.build.installBootLoader = initScriptBuilder; }; diff --git a/modules/system/boot/luksroot.nix b/modules/system/boot/luksroot.nix index 0e28a882da5..27c9c85eab3 100644 --- a/modules/system/boot/luksroot.nix +++ b/modules/system/boot/luksroot.nix @@ -5,7 +5,7 @@ with pkgs.lib; let luks = config.boot.initrd.luks; - openCommand = { name, device, ... }: '' + openCommand = { name, device, keyFile, keyFileSize, allowDiscards, ... }: '' # Wait for luksRoot to appear, e.g. if on a usb drive. # XXX: copied and adapted from stage-1-init.sh - should be # available as a function. @@ -19,8 +19,21 @@ let echo "ok" fi + ${optionalString (keyFile != null) '' + if ! test -e ${keyFile}; then + echo -n "waiting 10 seconds for key file ${keyFile} to appear..." + for try in $(seq 10); do + sleep 1 + if test -e ${keyFile}; then break; fi + echo -n . + done + echo "ok" + fi + ''} + # open luksRoot and scan for logical volumes - cryptsetup luksOpen ${device} ${name} + cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} \ + ${optionalString (keyFile != null) "--key-file=${keyFile} ${optionalString (keyFileSize != null) "--keyfile-size=${toString keyFileSize}"}"} ''; isPreLVM = f: f.preLVM; @@ -64,11 +77,46 @@ in description = "Path of the underlying block device."; }; + keyFile = mkOption { + default = null; + example = "/dev/sdb1"; + type = types.nullOr types.string; + description = '' + The name of the file (can be a raw device or a partition) that + should be used as the decryption key for the encrypted device. If + not specified, you will be prompted for a passphrase instead. + ''; + }; + + keyFileSize = mkOption { + default = null; + example = 4096; + type = types.nullOr types.int; + description = '' + The size of the key file. Use this if only the beginning of the + key file should be used as a key (often the case if a raw device + or partition is used as key file). If not specified, the whole + keyFile will be used decryption, instead of just + the first keyFileSize bytes. + ''; + }; + preLVM = mkOption { default = true; type = types.bool; description = "Whether the luksOpen will be attempted before LVM scan or after it."; }; + + allowDiscards = mkOption { + default = false; + type = types.bool; + description = '' + Whether to allow TRIM requests to the underlying device. This option + has security implications, please read the LUKS documentation before + activating in. + ''; + }; + }; }; }; diff --git a/modules/system/boot/stage-1-init.sh b/modules/system/boot/stage-1-init.sh index a232151967f..95e925bbe12 100644 --- a/modules/system/boot/stage-1-init.sh +++ b/modules/system/boot/stage-1-init.sh @@ -70,6 +70,7 @@ mount -t sysfs none /sys mount -t devtmpfs -o "size=@devSize@" none /dev mkdir -p /run mount -t tmpfs -o "mode=0755,size=@runSize@" none /run +mount -t securityfs none /sys/kernel/security # Process the kernel command line. export stage2Init=/init @@ -350,10 +351,10 @@ fi mkdir -m 0755 -p $targetRoot/proc $targetRoot/sys $targetRoot/dev $targetRoot/run -mount --bind /proc $targetRoot/proc -mount --bind /sys $targetRoot/sys -mount --bind /dev $targetRoot/dev -mount --bind /run $targetRoot/run +mount --move /proc $targetRoot/proc +mount --move /sys $targetRoot/sys +mount --move /dev $targetRoot/dev +mount --move /run $targetRoot/run exec switch_root "$targetRoot" "$stage2Init" diff --git a/modules/virtualisation/amazon-image.nix b/modules/virtualisation/amazon-image.nix index 203c9a724ce..9ada2b176fe 100644 --- a/modules/virtualisation/amazon-image.nix +++ b/modules/virtualisation/amazon-image.nix @@ -139,6 +139,10 @@ with pkgs.lib; cp ${pkgs.utillinux}/sbin/swapon $out/bin ''; + # Don't put old configurations in the GRUB menu. The user has no + # way to select them anyway. + boot.loader.grub.configurationLimit = 0; + # Allow root logins only using the SSH key that the user specified # at instance creation time. services.openssh.enable = true; diff --git a/modules/virtualisation/virtualbox-image.nix b/modules/virtualisation/virtualbox-image.nix index c3fbf344bfb..f049c5eb348 100644 --- a/modules/virtualisation/virtualbox-image.nix +++ b/modules/virtualisation/virtualbox-image.nix @@ -30,7 +30,7 @@ with pkgs.lib; mknod /dev/vda1 b $MAJOR $MINOR # Create an empty filesystem and mount it. - ${pkgs.e2fsprogs}/sbin/mkfs.ext3 -L nixos /dev/vda1 + ${pkgs.e2fsprogs}/sbin/mkfs.ext4 -L nixos /dev/vda1 ${pkgs.e2fsprogs}/sbin/tune2fs -c 0 -i 0 /dev/vda1 mkdir /mnt mount /dev/vda1 /mnt @@ -78,7 +78,7 @@ with pkgs.lib; ]; boot.loader.grub.version = 2; - boot.loader.grub.device = "/dev/vda"; + boot.loader.grub.device = "/dev/sda"; services.virtualbox.enable = true; } diff --git a/tests/installer.nix b/tests/installer.nix index 2b3232ca353..65542ae862e 100644 --- a/tests/installer.nix +++ b/tests/installer.nix @@ -22,7 +22,9 @@ let [ pkgs.glibcLocales pkgs.sudo pkgs.docbook5 + pkgs.docbook5_xsl pkgs.grub + pkgs.perlPackages.XMLLibXML ]; } ]; @@ -30,7 +32,7 @@ let # The configuration to install. - config = { fileSystems, testChannel, grubVersion }: pkgs.writeText "configuration.nix" + config = { fileSystems, testChannel, grubVersion, grubDevice }: pkgs.writeText "configuration.nix" '' { config, pkgs, modulesPath, ... }: @@ -43,9 +45,9 @@ let ${optionalString (grubVersion == 1) '' boot.loader.grub.splashImage = null; ''} - boot.loader.grub.device = "/dev/vda"; + boot.loader.grub.device = "${grubDevice}"; boot.loader.grub.extraConfig = "serial; terminal_output.serial"; - boot.initrd.kernelModules = [ "ext3" "virtio_console" ]; + boot.initrd.kernelModules = [ "ext3" "ext4" "xfs" "virtio_console" ]; fileSystems = [ ${fileSystems} ]; swapDevices = [ { label = "swap"; } ]; @@ -93,11 +95,14 @@ let # a test script fragment `createPartitions', which must create # partitions and filesystems, and a configuration.nix fragment # `fileSystems'. - testScriptFun = { createPartitions, fileSystems, testChannel, grubVersion }: + testScriptFun = { createPartitions, fileSystems, testChannel, grubVersion, grubDevice }: + let iface = if grubVersion == 1 then "scsi" else "virtio"; in '' createDisk("harddisk", 4 * 1024); - my $machine = createMachine({ hda => "harddisk", cdrom => glob("${iso}/iso/*.iso"), + my $machine = createMachine({ hda => "harddisk", + hdaInterface => "${iface}", + cdrom => glob("${iso}/iso/*.iso"), qemuFlags => '${optionalString testChannel (toString (qemuNICFlags 1 1 2))} ${optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"}'}); $machine->start; @@ -149,15 +154,9 @@ let print STDERR "Result of the hardware scan:\n$cfg\n"; $machine->copyFileFromHost( - "${ config { inherit fileSystems testChannel grubVersion; } }", + "${ config { inherit fileSystems testChannel grubVersion grubDevice; } }", "/mnt/etc/nixos/configuration.nix"); - # Hack to get GRUB 1 to install on virtio. GRUB 1 has a patch - # from Gentoo to support virtio, but it's incomplete: it doesn't - # detect /dev/vd* automatically. And we don't care enough about - # GRUB 1 to fix it. - $machine->mustSucceed("mkdir -p /mnt/boot/grub; echo '(hd0) /dev/vda' > /mnt/boot/grub/device.map"); - # Perform the installation. $machine->mustSucceed("nixos-install >&2"); @@ -167,7 +166,7 @@ let $machine->shutdown; # Now see if we can boot the installation. - my $machine = createMachine({ hda => "harddisk" }); + my $machine = createMachine({ hda => "harddisk", hdaInterface => "${iface}" }); # Did /boot get mounted, if appropriate? # !!! There is currently no good way to wait for the @@ -188,17 +187,17 @@ let # And just to be sure, check that the machine still boots after # "nixos-rebuild switch". - my $machine = createMachine({ hda => "harddisk" }); + my $machine = createMachine({ hda => "harddisk", hdaInterface => "${iface}" }); $machine->waitForJob("network-interfaces"); $machine->shutdown; ''; - makeTest = { createPartitions, fileSystems, testChannel ? false, grubVersion ? 2 }: + makeTest = { createPartitions, fileSystems, testChannel ? false, grubVersion ? 2, grubDevice ? "/dev/vda" }: { inherit iso; nodes = if testChannel then { inherit webserver; } else { }; testScript = testScriptFun { - inherit createPartitions fileSystems testChannel grubVersion; + inherit createPartitions fileSystems testChannel grubVersion grubDevice; }; }; @@ -268,7 +267,7 @@ in { "lvcreate --size 2G --name nixos MyVolGroup", "mkswap -f /dev/MyVolGroup/swap -L swap", "swapon -L swap", - "mkfs.ext3 -L nixos /dev/MyVolGroup/nixos", + "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", "mount LABEL=nixos /mnt", ); ''; @@ -313,18 +312,19 @@ in { { createPartitions = '' $machine->mustSucceed( - "parted /dev/vda mklabel msdos", - "parted /dev/vda -- mkpart primary linux-swap 1M 1024M", - "parted /dev/vda -- mkpart primary ext2 1024M -1s", + "parted /dev/sda mklabel msdos", + "parted /dev/sda -- mkpart primary linux-swap 1M 1024M", + "parted /dev/sda -- mkpart primary ext2 1024M -1s", "udevadm settle", - "mkswap /dev/vda1 -L swap", + "mkswap /dev/sda1 -L swap", "swapon -L swap", - "mkfs.ext3 -L nixos /dev/vda2", + "mkfs.ext3 -L nixos /dev/sda2", "mount LABEL=nixos /mnt", ); ''; fileSystems = rootFS; grubVersion = 1; + grubDevice = "/dev/sda"; }; # Rebuild the CD configuration with a little modification.