diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 6250fac0f0bb..d43fa2203818 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -191,6 +191,8 @@ in noCheck = true; }; + # In stage 1, mount a tmpfs on top of /nix/store (the squashfs + # image) to make this a live CD. fileSystems."/nix/.ro-store" = { fsType = "squashfs"; device = "/iso/nix-store.squashfs"; @@ -204,18 +206,16 @@ in neededForBoot = true; }; + fileSystems."/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro"; + }; + boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ]; boot.initrd.kernelModules = [ "loop" ]; - # In stage 1, mount a tmpfs on top of /nix/store (the squashfs - # image) to make this a live CD. - boot.initrd.postMountCommands = - '' - mkdir -p $targetRoot/nix/store - unionfs -o allow_other,cow,nonempty,chroot=$targetRoot,max_files=32768 /nix/.rw-store=RW:/nix/.ro-store=RO $targetRoot/nix/store - ''; - # Closures to be copied to the Nix store on the CD, namely the init # script and the top-level system configuration directory. isoImage.storeContents = @@ -311,8 +311,8 @@ in ''; # Add vfat support to the initrd to enable people to copy the - # contents of the CD to a bootable USB stick. Need unionfs-fuse for union mounts - boot.initrd.supportedFilesystems = [ "vfat" "unionfs-fuse" ]; + # contents of the CD to a bootable USB stick. + boot.initrd.supportedFilesystems = [ "vfat" ]; }; diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 7adb932aba7f..1b51c11e351a 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -4,7 +4,8 @@ targetRoot=/mnt-root console=tty1 export LD_LIBRARY_PATH=@extraUtils@/lib -export PATH=@extraUtils@/bin:@extraUtils@/sbin +export PATH=@extraUtils@/bin +ln -s @extraUtils@/bin /bin fail() { @@ -262,6 +263,13 @@ mountFS() { checkFS "$device" "$fsType" + # Create backing directories for unionfs-fuse. + if [ "$fsType" = unionfs-fuse ]; then + for i in $(IFS=:; echo ${options##*,dirs=}); do + mkdir -m 0700 -p /mnt-root"${i%=*}" + done + fi + echo "mounting $device on $mountPoint..." mkdir -p "/mnt-root$mountPoint" || true diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index b51ca9f7a362..58ff97671f3d 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -35,6 +35,7 @@ let } '' mkdir -p $out/bin $out/lib + ln -s $out/bin $out/sbin # Copy what we need from Glibc. cp -pv ${pkgs.glibc}/lib/ld*.so.? $out/lib @@ -46,11 +47,10 @@ let cp -pv ${pkgs.gcc.gcc}/lib*/libgcc_s.so.* $out/lib # Copy BusyBox. - cp -rvd ${pkgs.busybox}/{bin,sbin} $out/ - chmod -R u+w $out + cp -pvd ${pkgs.busybox}/bin/* ${pkgs.busybox}/sbin/* $out/bin/ # Copy some utillinux stuff. - cp -v ${pkgs.utillinux}/sbin/blkid $out/bin + cp -vf ${pkgs.utillinux}/sbin/blkid $out/bin cp -pdv ${pkgs.utillinux}/lib/libblkid*.so.* $out/lib cp -pdv ${pkgs.utillinux}/lib/libuuid*.so.* $out/lib @@ -73,7 +73,7 @@ let # Copy modprobe. cp -v ${pkgs.kmod}/bin/kmod $out/bin/ - ln -s kmod $out/bin/modprobe + ln -sf kmod $out/bin/modprobe ${config.boot.initrd.extraUtilsCommands} diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index ccb6b6160151..64a20034f3cc 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -68,7 +68,7 @@ let config = { mountPoint = mkDefault name; - device = mkIf (config.fsType == "tmpfs") config.fsType; + device = mkIf (config.fsType == "tmpfs") (mkDefault config.fsType); }; }; diff --git a/nixos/modules/tasks/filesystems/unionfs-fuse.nix b/nixos/modules/tasks/filesystems/unionfs-fuse.nix index 5b7777180568..fe195e0db0b6 100644 --- a/nixos/modules/tasks/filesystems/unionfs-fuse.nix +++ b/nixos/modules/tasks/filesystems/unionfs-fuse.nix @@ -2,14 +2,21 @@ { config = lib.mkMerge [ + (lib.mkIf (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.fuse}/sbin/mount.fuse $out/bin cp -v ${pkgs.unionfs-fuse}/bin/unionfs $out/bin + substitute ${pkgs.unionfs-fuse}/sbin/mount.unionfs-fuse $out/bin/mount.unionfs-fuse \ + --replace '${pkgs.bash}/bin/bash' /bin/sh \ + --replace '${pkgs.fuse}/sbin' /bin \ + --replace '${pkgs.unionfs-fuse}/bin' /bin + chmod +x $out/bin/mount.unionfs-fuse ''; - + boot.initrd.postDeviceCommands = '' # Hacky!!! fuse hard-codes the path to mount mkdir -p /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin @@ -17,8 +24,10 @@ ln -s $(which umount) /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${pkgs.utillinux.name}/bin ''; }) + (lib.mkIf (lib.any (fs: fs == "unionfs-fuse") config.boot.supportedFilesystems) { system.fsPackages = [ pkgs.unionfs-fuse ]; }) + ]; } diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix index bccf6583e47d..17acd08f086c 100644 --- a/nixos/modules/virtualisation/qemu-vm.nix +++ b/nixos/modules/virtualisation/qemu-vm.nix @@ -275,12 +275,10 @@ in boot.loader.grub.device = mkVMOverride "/dev/vda"; - boot.initrd.supportedFilesystems = optional cfg.writableStore "unionfs-fuse"; - boot.initrd.extraUtilsCommands = '' # We need mke2fs in the initrd. - cp ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin + cp -f ${pkgs.e2fsprogs}/sbin/mke2fs $out/bin ''; boot.initrd.postDeviceCommands = @@ -303,20 +301,6 @@ in chmod 1777 $targetRoot/tmp mkdir -p $targetRoot/boot - ${optionalString cfg.writableStore '' - mkdir -p /unionfs-chroot/ro-store - mount --rbind $targetRoot/nix/store /unionfs-chroot/ro-store - - mkdir /unionfs-chroot/rw-store - ${if cfg.writableStoreUseTmpfs then '' - mount -t tmpfs -o "mode=755" none /unionfs-chroot/rw-store - '' else '' - mkdir $targetRoot/.nix-rw-store - mount --bind $targetRoot/.nix-rw-store /unionfs-chroot/rw-store - ''} - - unionfs -o allow_other,cow,nonempty,chroot=/unionfs-chroot,max_files=32768,hide_meta_files /rw-store=RW:/ro-store=RO $targetRoot/nix/store - ''} ''; # After booting, register the closure of the paths in @@ -343,12 +327,13 @@ in # configuration, where the regular value for the `fileSystems' # attribute should be disregarded for the purpose of building a VM # test image (since those filesystems don't exist in the VM). - fileSystems = mkVMOverride + fileSystems = mkVMOverride ( { "/".device = "/dev/vda"; - "/nix/store" = + ${if cfg.writableStore then "/nix/.ro-store" else "/nix/store"} = { device = "store"; fsType = "9p"; options = "trans=virtio,version=9p2000.L,msize=1048576,cache=loose"; + neededForBoot = true; }; "/tmp/xchg" = { device = "xchg"; @@ -362,6 +347,18 @@ in options = "trans=virtio,version=9p2000.L,msize=1048576"; neededForBoot = true; }; + } // optionalAttrs cfg.writableStore + { "/nix/store" = + { fsType = "unionfs-fuse"; + device = "unionfs"; + options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro"; + }; + } // optionalAttrs (cfg.writableStore && cfg.writableStoreUseTmpfs) + { "/nix/.rw-store" = + { fsType = "tmpfs"; + options = "mode=0755"; + neededForBoot = true; + }; } // optionalAttrs cfg.useBootLoader { "/boot" = { device = "/dev/disk/by-label/boot"; @@ -369,7 +366,7 @@ in options = "ro"; noCheck = true; # fsck fails on a r/o filesystem }; - }; + }); swapDevices = mkVMOverride [ ]; boot.initrd.luks.devices = mkVMOverride [];