1import ./make-test-python.nix (
2 { pkgs, ... }:
3 {
4 name = "boot-stage2";
5
6 nodes.machine =
7 {
8 config,
9 pkgs,
10 lib,
11 ...
12 }:
13 {
14 virtualisation = {
15 emptyDiskImages = [ 256 ];
16
17 # Mount an ext4 as the upper layer of the Nix store.
18 fileSystems = {
19 "/nix/store" = lib.mkForce {
20 device = "/dev/vdb"; # the above disk image
21 fsType = "ext4";
22
23 # data=journal always displays after errors=remount-ro; this is only needed because of the overlay
24 # and #375257 will trigger with `errors=remount-ro` on a non-overlaid store:
25 # see ordering in https://github.com/torvalds/linux/blob/v6.12/fs/ext4/super.c#L2974
26 options = [
27 "defaults"
28 "errors=remount-ro"
29 "data=journal"
30 ];
31 };
32 };
33 };
34
35 boot = {
36 initrd = {
37 # Format the upper Nix store.
38 postDeviceCommands = ''
39 ${pkgs.e2fsprogs}/bin/mkfs.ext4 /dev/vdb
40 '';
41
42 # Overlay the RO store onto it.
43 # Note that bug #375257 can be triggered without an overlay,
44 # using the errors=remount-ro option (or similar) or with an overlay where any of the
45 # paths ends in 'ro'. The offending mountpoint also has to be the last (top) one
46 # if an option ending in 'ro' is the last in the list, so test both cases here.
47 postMountCommands = ''
48 mkdir -p /mnt-root/nix/store/ro /mnt-root/nix/store/rw /mnt-root/nix/store/work
49 mount --bind /mnt-root/nix/.ro-store /mnt-root/nix/store/ro
50 mount -t overlay overlay \
51 -o lowerdir=/mnt-root/nix/store/ro,upperdir=/mnt-root/nix/store/rw,workdir=/mnt-root/nix/store/work \
52 /mnt-root/nix/store
53 '';
54
55 kernelModules = [ "overlay" ];
56 };
57
58 postBootCommands = ''
59 touch /etc/post-boot-ran
60 mount
61 '';
62 };
63 };
64
65 testScript = ''
66 machine.wait_for_unit("multi-user.target")
67 machine.succeed("test /etc/post-boot-ran")
68 machine.fail("touch /nix/store/should-not-work");
69 '';
70
71 meta.maintainers = with pkgs.lib.maintainers; [ numinit ];
72 }
73)