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 # Whether to invoke switch-to-configuration boot during image creation
16, installBootLoader ? true
17
18, # The root file system type.
19 fsType ? "ext4"
20
21, # The initial NixOS configuration file to be copied to
22 # /etc/nixos/configuration.nix.
23 configFile ? null
24
25, # Shell code executed after the VM has finished.
26 postVM ? ""
27
28, name ? "nixos-disk-image"
29
30, format ? "raw"
31}:
32
33with lib;
34
35pkgs.vmTools.runInLinuxVM (
36 pkgs.runCommand name
37 { preVM =
38 ''
39 mkdir $out
40 diskImage=$out/nixos.${if format == "qcow2" then "qcow2" else "img"}
41 ${pkgs.vmTools.qemu}/bin/qemu-img create -f ${format} $diskImage "${toString diskSize}M"
42 mv closure xchg/
43 '';
44 buildInputs = [ pkgs.utillinux pkgs.perl pkgs.e2fsprogs pkgs.parted ];
45 exportReferencesGraph =
46 [ "closure" config.system.build.toplevel ];
47 inherit postVM;
48 memSize = 1024;
49 }
50 ''
51 ${if partitioned then ''
52 # Create a single / partition.
53 parted /dev/vda mklabel msdos
54 parted /dev/vda -- mkpart primary ext2 1M -1s
55 . /sys/class/block/vda1/uevent
56 mknod /dev/vda1 b $MAJOR $MINOR
57 rootDisk=/dev/vda1
58 '' else ''
59 rootDisk=/dev/vda
60 ''}
61
62 # Create an empty filesystem and mount it.
63 mkfs.${fsType} -L nixos $rootDisk
64 ${optionalString (fsType == "ext4") ''
65 tune2fs -c 0 -i 0 $rootDisk
66 ''}
67 mkdir /mnt
68 mount $rootDisk /mnt
69
70 # Register the paths in the Nix database.
71 printRegistration=1 perl ${pkgs.pathsFromGraph} /tmp/xchg/closure | \
72 ${config.nix.package.out}/bin/nix-store --load-db --option build-users-group ""
73
74 # Add missing size/hash fields to the database. FIXME:
75 # exportReferencesGraph should provide these directly.
76 ${config.nix.package.out}/bin/nix-store --verify --check-contents --option build-users-group ""
77
78 # In case the bootloader tries to write to /dev/sda…
79 ln -s vda /dev/xvda
80 ln -s vda /dev/sda
81
82 # Install the closure onto the image
83 USER=root ${config.system.build.nixos-install}/bin/nixos-install \
84 --closure ${config.system.build.toplevel} \
85 --no-channel-copy \
86 --no-root-passwd \
87 ${optionalString (!installBootLoader) "--no-bootloader"}
88
89 # Install a configuration.nix.
90 mkdir -p /mnt/etc/nixos
91 ${optionalString (configFile != null) ''
92 cp ${configFile} /mnt/etc/nixos/configuration.nix
93 ''}
94
95 # Remove /etc/machine-id so that each machine cloning this image will get its own id
96 rm -f /mnt/etc/machine-id
97
98 umount /mnt
99
100 # Do a fsck to make sure resize2fs works.
101 fsck.${fsType} -f -y $rootDisk
102 ''
103)