1{ pkgs 2, lib 3 4, # The NixOS configuration to be installed onto the disk image. 5 config 6 7, # The size of the disk, in megabytes. 8 diskSize 9 10, # Whether the disk should be partitioned (with a single partition 11 # containing the root filesystem) or contain the root filesystem 12 # directly. 13 partitioned ? true 14 15, # The root file system type. 16 fsType ? "ext4" 17 18, # The initial NixOS configuration file to be copied to 19 # /etc/nixos/configuration.nix. 20 configFile ? null 21 22, # Shell code executed after the VM has finished. 23 postVM ? "" 24 25}: 26 27with lib; 28 29pkgs.vmTools.runInLinuxVM ( 30 pkgs.runCommand "nixos-disk-image" 31 { preVM = 32 '' 33 mkdir $out 34 diskImage=$out/nixos.img 35 ${pkgs.vmTools.qemu}/bin/qemu-img create -f raw $diskImage "${toString diskSize}M" 36 mv closure xchg/ 37 ''; 38 buildInputs = [ pkgs.utillinux pkgs.perl pkgs.e2fsprogs pkgs.parted ]; 39 exportReferencesGraph = 40 [ "closure" config.system.build.toplevel ]; 41 inherit postVM; 42 memSize = 1024; 43 } 44 '' 45 ${if partitioned then '' 46 # Create a single / partition. 47 parted /dev/vda mklabel msdos 48 parted /dev/vda -- mkpart primary ext2 1M -1s 49 . /sys/class/block/vda1/uevent 50 mknod /dev/vda1 b $MAJOR $MINOR 51 rootDisk=/dev/vda1 52 '' else '' 53 rootDisk=/dev/vda 54 ''} 55 56 # Create an empty filesystem and mount it. 57 mkfs.${fsType} -L nixos $rootDisk 58 ${optionalString (fsType == "ext4") '' 59 tune2fs -c 0 -i 0 $rootDisk 60 ''} 61 mkdir /mnt 62 mount $rootDisk /mnt 63 64 # The initrd expects these directories to exist. 65 mkdir /mnt/dev /mnt/proc /mnt/sys 66 67 mount -o bind /proc /mnt/proc 68 mount -o bind /dev /mnt/dev 69 mount -o bind /sys /mnt/sys 70 71 # Copy all paths in the closure to the filesystem. 72 storePaths=$(perl ${pkgs.pathsFromGraph} /tmp/xchg/closure) 73 74 mkdir -p /mnt/nix/store 75 echo "copying everything (will take a while)..." 76 set -f 77 cp -prd $storePaths /mnt/nix/store/ 78 79 # Register the paths in the Nix database. 80 printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \ 81 chroot /mnt ${config.nix.package}/bin/nix-store --load-db --option build-users-group "" 82 83 # Add missing size/hash fields to the database. FIXME: 84 # exportReferencesGraph should provide these directly. 85 chroot /mnt ${config.nix.package}/bin/nix-store --verify --check-contents 86 87 # Create the system profile to allow nixos-rebuild to work. 88 chroot /mnt ${config.nix.package}/bin/nix-env --option build-users-group "" \ 89 -p /nix/var/nix/profiles/system --set ${config.system.build.toplevel} 90 91 # `nixos-rebuild' requires an /etc/NIXOS. 92 mkdir -p /mnt/etc 93 touch /mnt/etc/NIXOS 94 95 # `switch-to-configuration' requires a /bin/sh 96 mkdir -p /mnt/bin 97 ln -s ${config.system.build.binsh}/bin/sh /mnt/bin/sh 98 99 # Install a configuration.nix. 100 mkdir -p /mnt/etc/nixos 101 ${optionalString (configFile != null) '' 102 cp ${configFile} /mnt/etc/nixos/configuration.nix 103 ''} 104 105 # Generate the GRUB menu. 106 ln -s vda /dev/xvda 107 ln -s vda /dev/sda 108 chroot /mnt ${config.system.build.toplevel}/bin/switch-to-configuration boot 109 110 umount /mnt/proc /mnt/dev /mnt/sys 111 umount /mnt 112 113 # Do a fsck to make sure resize2fs works. 114 fsck.${fsType} -f -y $rootDisk 115 '' 116)