diff --git a/modules/installer/cd-dvd/iso-image.nix b/modules/installer/cd-dvd/iso-image.nix index 96fc8a31dca2..33000a3fbf1d 100644 --- a/modules/installer/cd-dvd/iso-image.nix +++ b/modules/installer/cd-dvd/iso-image.nix @@ -192,15 +192,7 @@ in options = "loop"; }; - # We need squashfs in the initrd to mount the compressed Nix store, - # and aufs to make the root filesystem appear writable. - boot.extraModulePackages = - if config.boot.kernelPackages.aufs == null then - abort "This kernel doesn't have aufs enabled" - else - [ config.boot.kernelPackages.aufs ]; - - boot.initrd.availableKernelModules = [ "aufs" "squashfs" "iso9660" ]; + boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ]; boot.initrd.kernelModules = [ "loop" ]; @@ -210,16 +202,20 @@ in # /nix/store (the squashfs image) to make this a live CD. boot.initrd.postMountCommands = '' - mkdir /mnt-root-tmpfs - mount -t tmpfs -o "mode=755" none /mnt-root-tmpfs + mkdir -p /unionfs-chroot/ro-root + mount --rbind $targetRoot /unionfs-chroot/ro-root + + mkdir /unionfs-chroot/rw-root + mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-root mkdir /mnt-root-union - mount -t aufs -o dirs=/mnt-root-tmpfs=rw:$targetRoot=ro none /mnt-root-union + unionfs -o allow_other,cow,chroot=/unionfs-chroot /rw-root=RW:/ro-root=RO /mnt-root-union + oldTargetRoot=$targetRoot targetRoot=/mnt-root-union - mkdir /mnt-store-tmpfs - mount -t tmpfs -o "mode=755" none /mnt-store-tmpfs - mkdir -p $targetRoot/nix/store - mount -t aufs -o dirs=/mnt-store-tmpfs=rw:/mnt-root/nix/store=ro none /mnt-root-union/nix/store + mkdir /unionfs-chroot/rw-store + mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-store + mkdir -p $oldTargetRoot/nix/store + unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot /rw-store=RW:/ro-root/nix/store=RO /mnt-root-union/nix/store ''; # Closures to be copied to the Nix store on the CD, namely the init @@ -311,7 +307,7 @@ in ''; # Add vfat support to the initrd to enable people to copy the - # contents of the CD to a bootable USB stick. - boot.initrd.supportedFilesystems = [ "vfat" ]; + # contents of the CD to a bootable USB stick. Need unionfs-fuse for union mounts + boot.initrd.supportedFilesystems = [ "vfat" "unionfs-fuse" ]; } diff --git a/modules/module-list.nix b/modules/module-list.nix index 467eac6e00e4..ae5e5d5c49f6 100644 --- a/modules/module-list.nix +++ b/modules/module-list.nix @@ -214,6 +214,7 @@ ./tasks/filesystems/ext.nix ./tasks/filesystems/nfs.nix ./tasks/filesystems/reiserfs.nix + ./tasks/filesystems/unionfs-fuse.nix ./tasks/filesystems/vfat.nix ./tasks/filesystems/xfs.nix ./tasks/kbd.nix diff --git a/modules/system/boot/kernel.nix b/modules/system/boot/kernel.nix index 4b6436a77f76..3637378d4d1e 100644 --- a/modules/system/boot/kernel.nix +++ b/modules/system/boot/kernel.nix @@ -64,7 +64,7 @@ in boot.extraModulePackages = mkOption { default = []; - # !!! example = [pkgs.aufs pkgs.nvidia_x11]; + # !!! example = [pkgs.nvidia_x11]; description = "A list of additional packages supplying kernel modules."; }; diff --git a/modules/system/boot/stage-1-init.sh b/modules/system/boot/stage-1-init.sh index 23207babe3fa..778e36cfd36e 100644 --- a/modules/system/boot/stage-1-init.sh +++ b/modules/system/boot/stage-1-init.sh @@ -332,8 +332,8 @@ exec 3>&- udevadm control --exit || true # Kill any remaining processes, just to be sure we're not taking any -# with us into stage 2. -pkill -9 -v 1 +# with us into stage 2. unionfs-fuse mounts require the unionfs process. +pkill -9 -v '(1|unionfs)' if test -n "$debug1mounts"; then fail; fi diff --git a/modules/tasks/filesystems/unionfs-fuse.nix b/modules/tasks/filesystems/unionfs-fuse.nix new file mode 100644 index 000000000000..48cf798c7f0a --- /dev/null +++ b/modules/tasks/filesystems/unionfs-fuse.nix @@ -0,0 +1,19 @@ +{ config, pkgs, ... }: + +{ + config = pkgs.lib.mkIf (pkgs.lib.any (fs: fs == "unionfs-fuse") config.boot.initrd.supportedFilesystems) { + boot.initrd.kernelModules = [ "fuse" ]; + + boot.initrd.extraUtilsCommands = '' + cp -v ${pkgs.fuse}/lib/libfuse* $out/lib + cp -v ${pkgs.unionfs-fuse}/bin/unionfs $out/bin + ''; + + boot.initrd.postDeviceCommands = '' + # Hacky!!! fuse hard-codes the path to mount + mkdir -p /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin + ln -s $(which mount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin + ln -s $(which umount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin + ''; + }; +} diff --git a/modules/virtualisation/amazon-image.nix b/modules/virtualisation/amazon-image.nix index da6f6d3afc92..79fb435db386 100644 --- a/modules/virtualisation/amazon-image.nix +++ b/modules/virtualisation/amazon-image.nix @@ -64,11 +64,9 @@ with pkgs.lib; fileSystems."/".device = "/dev/disk/by-label/nixos"; - boot.initrd.kernelModules = [ "xen-blkfront" "aufs" ]; + boot.initrd.kernelModules = [ "xen-blkfront" ]; boot.kernelModules = [ "xen-netfront" ]; - boot.extraModulePackages = [ config.boot.kernelPackages.aufs ]; - # Generate a GRUB menu. Amazon's pv-grub uses this to boot our kernel/initrd. boot.loader.grub.device = "nodev"; boot.loader.grub.timeout = 0; @@ -89,12 +87,12 @@ with pkgs.lib; # while "m1.large" has two ephemeral filesystems and no swap # devices). Also, put /tmp and /var on /disk0, since it has a lot # more space than the root device. Similarly, "move" /nix to /disk0 - # by layering an AUFS on top of it so we have a lot more space for + # by layering a unionfs-fuse mount on top of it so we have a lot more space for # Nix operations. boot.initrd.postMountCommands = '' diskNr=0 - diskForAufs= + diskForUnionfs= for device in /dev/xvd[abcde]*; do if [ "$device" = /dev/xvda -o "$device" = /dev/xvda1 ]; then continue; fi fsType=$(blkid -o value -s TYPE "$device" || true) @@ -106,25 +104,31 @@ with pkgs.lib; diskNr=$((diskNr + 1)) echo "mounting $device on $mp..." if mountFS "$device" "$mp" "" ext3; then - if [ -z "$diskForAufs" ]; then diskForAufs="$mp"; fi + if [ -z "$diskForUnionfs" ]; then diskForUnionfs="$mp"; fi fi else echo "skipping unknown device type $device" fi done - if [ -n "$diskForAufs" ]; then - mkdir -m 755 -p $targetRoot/$diskForAufs/root + if [ -n "$diskForUnionfs" ]; then + mkdir -m 755 -p $targetRoot/$diskForUnionfs/root - mkdir -m 1777 -p $targetRoot/$diskForAufs/root/tmp $targetRoot/tmp - mount --bind $targetRoot/$diskForAufs/root/tmp $targetRoot/tmp + mkdir -m 1777 -p $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp + mount --bind $targetRoot/$diskForUnionfs/root/tmp $targetRoot/tmp if [ ! -e $targetRoot/.ebs ]; then - mkdir -m 755 -p $targetRoot/$diskForAufs/root/var $targetRoot/var - mount --bind $targetRoot/$diskForAufs/root/var $targetRoot/var + mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/var $targetRoot/var + mount --bind $targetRoot/$diskForUnionfs/root/var $targetRoot/var - mkdir -m 755 -p $targetRoot/$diskForAufs/root/nix - mount -t aufs -o dirs=$targetRoot/$diskForAufs/root/nix=rw:$targetRoot/nix=rr none $targetRoot/nix + mkdir -p /unionfs-chroot/ro-nix + mount --rbind $targetRoot/nix /unionfs-chroot/ro-nix + + mkdir -m 755 -p $targetRoot/$diskForUnionfs/root/nix + mkdir -p /unionfs-chroot/rw-nix + mount --rbind $targetRoot/$diskForUnionfs/root/nix /unionfs-chroot/rw-nix + + unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot /rw-nix=RW:/ro-nix=RO $targetRoot/nix fi fi ''; @@ -149,4 +153,6 @@ with pkgs.lib; # Always include cryptsetup so that Charon can use it. environment.systemPackages = [ pkgs.cryptsetup ]; + + boot.initrd.supportedFilesystems = [ "unionfs-fuse" ]; } diff --git a/modules/virtualisation/nova-image.nix b/modules/virtualisation/nova-image.nix index 2aa78aeaddab..0ce5d218cdb4 100644 --- a/modules/virtualisation/nova-image.nix +++ b/modules/virtualisation/nova-image.nix @@ -72,10 +72,6 @@ with pkgs.lib; boot.kernelParams = [ "console=ttyS0" ]; - boot.initrd.kernelModules = [ "aufs" ]; - - boot.extraModulePackages = [ config.boot.kernelPackages.aufs ]; - boot.loader.grub.version = 2; boot.loader.grub.device = "/dev/vda"; boot.loader.grub.timeout = 0; @@ -83,8 +79,8 @@ with pkgs.lib; # Put /tmp and /var on /ephemeral0, which has a lot more space. # Unfortunately we can't do this with the `fileSystems' option # because it has no support for creating the source of a bind - # mount. Also, "move" /nix to /ephemeral0 by layering an AUFS - # on top of it so we have a lot more space for Nix operations. + # mount. Also, "move" /nix to /ephemeral0 by layering a unionfs-fuse + # mount on top of it so we have a lot more space for Nix operations. /* boot.initrd.postMountCommands = '' @@ -96,9 +92,16 @@ with pkgs.lib; mkdir -m 755 -p $targetRoot/var mount --bind $targetRoot/ephemeral0/var $targetRoot/var + mkdir -p /unionfs-chroot/ro-nix + mount --rbind $targetRoot/nix /unionfs-chroot/ro-nix + + mkdir -p /unionfs-chroot/rw-nix mkdir -m 755 -p $targetRoot/ephemeral0/nix - mount -t aufs -o dirs=$targetRoot/ephemeral0/nix=rw:$targetRoot/nix=rr none $targetRoot/nix + mount --rbind $targetRoot/ephemeral0/nix /unionfs-chroot/rw-nix + unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot /rw-nix=RW:/ro-nix=RO $targetRoot/nix ''; + + boot.initrd.supportedFilesystems = [ "unionfs-fuse" ]; */ # Since Nova allows VNC access to instances, it's nice to start to diff --git a/modules/virtualisation/qemu-vm.nix b/modules/virtualisation/qemu-vm.nix index 22e5017d7c08..0367379b2444 100644 --- a/modules/virtualisation/qemu-vm.nix +++ b/modules/virtualisation/qemu-vm.nix @@ -95,7 +95,7 @@ let description = '' If enabled, the Nix store in the VM is made writable by - layering an AUFS/tmpfs filesystem on top of the host's Nix + layering a unionfs-fuse/tmpfs filesystem on top of the host's Nix store. ''; }; @@ -250,11 +250,9 @@ in # CIFS. Also use paravirtualised network and block devices for # performance. boot.initrd.availableKernelModules = - [ "cifs" "nls_utf8" "hmac" "md4" "ecb" "des_generic" ] - ++ optional cfg.writableStore [ "aufs" ]; + [ "cifs" "nls_utf8" "hmac" "md4" "ecb" "des_generic" ]; - boot.extraModulePackages = - optional cfg.writableStore config.boot.kernelPackages.aufs; + boot.initrd.supportedFilesystems = optional cfg.writableStore "unionfs-fuse"; boot.initrd.extraUtilsCommands = '' @@ -288,9 +286,12 @@ in mkdir -p $targetRoot/boot mount -o remount,ro $targetRoot/nix/store ${optionalString cfg.writableStore '' - mkdir /mnt-store-tmpfs - mount -t tmpfs -o "mode=755" none /mnt-store-tmpfs - mount -t aufs -o dirs=/mnt-store-tmpfs=rw:$targetRoot/nix/store=rr none $targetRoot/nix/store + mkdir -p /unionfs-chroot/ro-store + mount --rbind $targetRoot/nix/store /unionfs-chroot/ro-store + + mkdir /unionfs-chroot/rw-store + mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-store + unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot /rw-store=RW:/ro-store=RO $targetRoot/nix/store ''} '';