at 24.11-pre 52 kB view raw
1{ system ? builtins.currentSystem, 2 config ? {}, 3 pkgs ? import ../.. { inherit system config; }, 4 systemdStage1 ? false 5}: 6 7with import ../lib/testing-python.nix { inherit system pkgs; }; 8with pkgs.lib; 9 10let 11 12 # The configuration to install. 13 makeConfig = { bootLoader, grubDevice, grubIdentifier, grubUseEfi 14 , extraConfig, forceGrubReinstallCount ? 0, flake ? false 15 , clevisTest 16 }: 17 pkgs.writeText "configuration.nix" '' 18 { config, lib, pkgs, modulesPath, ... }: 19 20 { imports = 21 [ ./hardware-configuration.nix 22 ${if flake 23 then "" # Still included, but via installer/flake.nix 24 else "<nixpkgs/nixos/modules/testing/test-instrumentation.nix>"} 25 ]; 26 27 networking.hostName = "thatworked"; 28 29 documentation.enable = false; 30 31 # To ensure that we can rebuild the grub configuration on the nixos-rebuild 32 system.extraDependencies = with pkgs; [ stdenvNoCC ]; 33 34 ${optionalString systemdStage1 "boot.initrd.systemd.enable = true;"} 35 36 ${optionalString (bootLoader == "grub") '' 37 boot.loader.grub.extraConfig = "serial; terminal_output serial"; 38 ${if grubUseEfi then '' 39 boot.loader.grub.device = "nodev"; 40 boot.loader.grub.efiSupport = true; 41 boot.loader.grub.efiInstallAsRemovable = true; # XXX: needed for OVMF? 42 '' else '' 43 boot.loader.grub.device = "${grubDevice}"; 44 boot.loader.grub.fsIdentifier = "${grubIdentifier}"; 45 ''} 46 47 boot.loader.grub.configurationLimit = 100 + ${toString forceGrubReinstallCount}; 48 ''} 49 50 ${optionalString (bootLoader == "systemd-boot") '' 51 boot.loader.systemd-boot.enable = true; 52 ''} 53 54 boot.initrd.secrets."/etc/secret" = "/etc/nixos/secret"; 55 56 ${optionalString clevisTest '' 57 boot.kernelParams = [ "console=tty0" "ip=192.168.1.1:::255.255.255.0::eth1:none" ]; 58 boot.initrd = { 59 availableKernelModules = [ "tpm_tis" ]; 60 clevis = { enable = true; useTang = true; }; 61 network.enable = true; 62 }; 63 ''} 64 65 users.users.alice = { 66 isNormalUser = true; 67 home = "/home/alice"; 68 description = "Alice Foobar"; 69 }; 70 71 hardware.enableAllFirmware = lib.mkForce false; 72 73 ${replaceStrings ["\n"] ["\n "] extraConfig} 74 } 75 ''; 76 77 78 # The test script boots a NixOS VM, installs NixOS on an empty hard 79 # disk, and then reboot from the hard disk. It's parameterized with 80 # a test script fragment `createPartitions', which must create 81 # partitions and filesystems. 82 testScriptFun = { bootLoader, createPartitions, grubDevice, grubUseEfi, grubIdentifier 83 , postInstallCommands, postBootCommands, extraConfig 84 , testSpecialisationConfig, testFlakeSwitch, clevisTest, clevisFallbackTest 85 , disableFileSystems 86 }: 87 let 88 startTarget = '' 89 ${optionalString clevisTest "tpm.start()"} 90 target.start() 91 ${postBootCommands} 92 target.wait_for_unit("multi-user.target") 93 ''; 94 in '' 95 ${optionalString clevisTest '' 96 import os 97 import subprocess 98 99 tpm_folder = os.environ['NIX_BUILD_TOP'] 100 101 class Tpm: 102 def __init__(self): 103 self.start() 104 105 def start(self): 106 self.proc = subprocess.Popen(["${pkgs.swtpm}/bin/swtpm", 107 "socket", 108 "--tpmstate", f"dir={tpm_folder}/swtpm", 109 "--ctrl", f"type=unixio,path={tpm_folder}/swtpm-sock", 110 "--tpm2" 111 ]) 112 113 # Check whether starting swtpm failed 114 try: 115 exit_code = self.proc.wait(timeout=0.2) 116 if exit_code is not None and exit_code != 0: 117 raise Exception("failed to start swtpm") 118 except subprocess.TimeoutExpired: 119 pass 120 121 """Check whether the swtpm process exited due to an error""" 122 def check(self): 123 exit_code = self.proc.poll() 124 if exit_code is not None and exit_code != 0: 125 raise Exception("swtpm process died") 126 127 128 os.mkdir(f"{tpm_folder}/swtpm") 129 tpm = Tpm() 130 tpm.check() 131 ''} 132 133 installer.start() 134 ${optionalString clevisTest '' 135 tang.start() 136 tang.wait_for_unit("sockets.target") 137 tang.systemctl("start network-online.target") 138 tang.wait_for_unit("network-online.target") 139 installer.systemctl("start network-online.target") 140 installer.wait_for_unit("network-online.target") 141 ''} 142 installer.wait_for_unit("multi-user.target") 143 144 with subtest("Assert readiness of login prompt"): 145 installer.succeed("echo hello") 146 147 with subtest("Wait for hard disks to appear in /dev"): 148 installer.succeed("udevadm settle") 149 150 ${createPartitions} 151 152 with subtest("Create the NixOS configuration"): 153 installer.succeed("nixos-generate-config ${optionalString disableFileSystems "--no-filesystems"} --root /mnt") 154 installer.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2") 155 installer.copy_from_host( 156 "${ makeConfig { 157 inherit bootLoader grubDevice grubIdentifier 158 grubUseEfi extraConfig clevisTest; 159 } 160 }", 161 "/mnt/etc/nixos/configuration.nix", 162 ) 163 installer.copy_from_host("${pkgs.writeText "secret" "secret"}", "/mnt/etc/nixos/secret") 164 165 ${optionalString clevisTest '' 166 with subtest("Create the Clevis secret with Tang"): 167 installer.systemctl("start network-online.target") 168 installer.wait_for_unit("network-online.target") 169 installer.succeed('echo -n password | clevis encrypt sss \'{"t": 2, "pins": {"tpm2": {}, "tang": {"url": "http://192.168.1.2"}}}\' -y > /mnt/etc/nixos/clevis-secret.jwe')''} 170 171 ${optionalString clevisFallbackTest '' 172 with subtest("Shutdown Tang to check fallback to interactive prompt"): 173 tang.shutdown() 174 ''} 175 176 with subtest("Perform the installation"): 177 installer.succeed("nixos-install < /dev/null >&2") 178 179 with subtest("Do it again to make sure it's idempotent"): 180 installer.succeed("nixos-install < /dev/null >&2") 181 182 with subtest("Check that we can build things in nixos-enter"): 183 installer.succeed( 184 """ 185 nixos-enter -- nix-build --option substitute false -E 'derivation { 186 name = "t"; 187 builder = "/bin/sh"; 188 args = ["-c" "echo nixos-enter build > $out"]; 189 system = builtins.currentSystem; 190 preferLocalBuild = true; 191 }' 192 """ 193 ) 194 195 ${postInstallCommands} 196 197 with subtest("Shutdown system after installation"): 198 installer.succeed("umount -R /mnt") 199 installer.succeed("sync") 200 installer.shutdown() 201 202 # We're actually the same machine, just booting differently this time. 203 target.state_dir = installer.state_dir 204 205 # Now see if we can boot the installation. 206 ${startTarget} 207 208 with subtest("Assert that /boot get mounted"): 209 target.wait_for_unit("local-fs.target") 210 ${if bootLoader == "grub" 211 then ''target.succeed("test -e /boot/grub")'' 212 else ''target.succeed("test -e /boot/loader/loader.conf")'' 213 } 214 215 with subtest("Check whether /root has correct permissions"): 216 assert "700" in target.succeed("stat -c '%a' /root") 217 218 with subtest("Assert swap device got activated"): 219 # uncomment once https://bugs.freedesktop.org/show_bug.cgi?id=86930 is resolved 220 target.wait_for_unit("swap.target") 221 target.succeed("cat /proc/swaps | grep -q /dev") 222 223 with subtest("Check that the store is in good shape"): 224 target.succeed("nix-store --verify --check-contents >&2") 225 226 with subtest("Check whether the channel works"): 227 target.succeed("nix-env -iA nixos.procps >&2") 228 assert ".nix-profile" in target.succeed("type -tP ps | tee /dev/stderr") 229 230 with subtest( 231 "Check that the daemon works, and that non-root users can run builds " 232 "(this will build a new profile generation through the daemon)" 233 ): 234 target.succeed("su alice -l -c 'nix-env -iA nixos.procps' >&2") 235 236 with subtest("Configure system with writable Nix store on next boot"): 237 # we're not using copy_from_host here because the installer image 238 # doesn't know about the host-guest sharing mechanism. 239 target.copy_from_host_via_shell( 240 "${ makeConfig { 241 inherit bootLoader grubDevice grubIdentifier 242 grubUseEfi extraConfig clevisTest; 243 forceGrubReinstallCount = 1; 244 } 245 }", 246 "/etc/nixos/configuration.nix", 247 ) 248 249 with subtest("Check whether nixos-rebuild works"): 250 target.succeed("nixos-rebuild switch >&2") 251 252 with subtest("Test nixos-option"): 253 kernel_modules = target.succeed("nixos-option boot.initrd.kernelModules") 254 assert "virtio_console" in kernel_modules 255 assert "List of modules" in kernel_modules 256 assert "qemu-guest.nix" in kernel_modules 257 258 target.shutdown() 259 260 # Check whether a writable store build works 261 ${startTarget} 262 263 # we're not using copy_from_host here because the installer image 264 # doesn't know about the host-guest sharing mechanism. 265 target.copy_from_host_via_shell( 266 "${ makeConfig { 267 inherit bootLoader grubDevice grubIdentifier 268 grubUseEfi extraConfig clevisTest; 269 forceGrubReinstallCount = 2; 270 } 271 }", 272 "/etc/nixos/configuration.nix", 273 ) 274 target.succeed("nixos-rebuild boot >&2") 275 target.shutdown() 276 277 # And just to be sure, check that the target still boots after "nixos-rebuild switch". 278 ${startTarget} 279 target.wait_for_unit("network.target") 280 281 # Sanity check, is it the configuration.nix we generated? 282 hostname = target.succeed("hostname").strip() 283 assert hostname == "thatworked" 284 285 target.shutdown() 286 287 # Tests for validating clone configuration entries in grub menu 288 '' 289 + optionalString testSpecialisationConfig '' 290 # Reboot target 291 ${startTarget} 292 293 with subtest("Booted configuration name should be 'Home'"): 294 # This is not the name that shows in the grub menu. 295 # The default configuration is always shown as "Default" 296 target.succeed("cat /run/booted-system/configuration-name >&2") 297 assert "Home" in target.succeed("cat /run/booted-system/configuration-name") 298 299 with subtest("We should **not** find a file named /etc/gitconfig"): 300 target.fail("test -e /etc/gitconfig") 301 302 with subtest("Set grub to boot the second configuration"): 303 target.succeed("grub-reboot 1") 304 305 target.shutdown() 306 307 # Reboot target 308 ${startTarget} 309 310 with subtest("Booted configuration name should be Work"): 311 target.succeed("cat /run/booted-system/configuration-name >&2") 312 assert "Work" in target.succeed("cat /run/booted-system/configuration-name") 313 314 with subtest("We should find a file named /etc/gitconfig"): 315 target.succeed("test -e /etc/gitconfig") 316 317 target.shutdown() 318 '' 319 + optionalString testFlakeSwitch '' 320 ${startTarget} 321 322 with subtest("Configure system with flake"): 323 # TODO: evaluate as user? 324 target.succeed(""" 325 mkdir /root/my-config 326 mv /etc/nixos/hardware-configuration.nix /root/my-config/ 327 rm /etc/nixos/configuration.nix 328 """) 329 target.copy_from_host_via_shell( 330 "${makeConfig { 331 inherit bootLoader grubDevice grubIdentifier grubUseEfi extraConfig clevisTest; 332 forceGrubReinstallCount = 1; 333 flake = true; 334 }}", 335 "/root/my-config/configuration.nix", 336 ) 337 target.copy_from_host_via_shell( 338 "${./installer/flake.nix}", 339 "/root/my-config/flake.nix", 340 ) 341 target.succeed(""" 342 # for some reason the image does not have `pkgs.path`, so 343 # we use readlink to find a Nixpkgs source. 344 pkgs=$(readlink -f /nix/var/nix/profiles/per-user/root/channels)/nixos 345 if ! [[ -e $pkgs/pkgs/top-level/default.nix ]]; then 346 echo 1>&2 "$pkgs does not seem to be a nixpkgs source. Please fix the test so that pkgs points to a nixpkgs source."; 347 exit 1; 348 fi 349 sed -e s^@nixpkgs@^$pkgs^ -i /root/my-config/flake.nix 350 """) 351 352 with subtest("Switch to flake based config"): 353 target.succeed("nixos-rebuild switch --flake /root/my-config#xyz") 354 355 target.shutdown() 356 357 ${startTarget} 358 359 with subtest("nix-channel command is not available anymore"): 360 target.succeed("! which nix-channel") 361 362 # Note that the channel profile is still present on disk, but configured 363 # not to be used. 364 with subtest("builtins.nixPath is now empty"): 365 target.succeed(""" 366 [[ "[ ]" == "$(nix-instantiate builtins.nixPath --eval --expr)" ]] 367 """) 368 369 with subtest("<nixpkgs> does not resolve"): 370 target.succeed(""" 371 ! nix-instantiate '<nixpkgs>' --eval --expr 372 """) 373 374 with subtest("Evaluate flake config in fresh env without nix-channel"): 375 target.succeed("nixos-rebuild switch --flake /root/my-config#xyz") 376 377 with subtest("Evaluate flake config in fresh env without channel profiles"): 378 target.succeed(""" 379 ( 380 exec 1>&2 381 rm -v /root/.nix-channels 382 rm -vrf ~/.nix-defexpr 383 rm -vrf /nix/var/nix/profiles/per-user/root/channels* 384 ) 385 """) 386 target.succeed("nixos-rebuild switch --flake /root/my-config#xyz") 387 388 target.shutdown() 389 ''; 390 391 392 makeInstallerTest = name: 393 { createPartitions 394 , postInstallCommands ? "", postBootCommands ? "" 395 , extraConfig ? "" 396 , extraInstallerConfig ? {} 397 , bootLoader ? "grub" # either "grub" or "systemd-boot" 398 , grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false 399 , enableOCR ? false, meta ? {} 400 , testSpecialisationConfig ? false 401 , testFlakeSwitch ? false 402 , clevisTest ? false 403 , clevisFallbackTest ? false 404 , disableFileSystems ? false 405 }: 406 let 407 isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); 408 in makeTest { 409 inherit enableOCR; 410 name = "installer-" + name; 411 meta = { 412 # put global maintainers here, individuals go into makeInstallerTest fkt call 413 maintainers = (meta.maintainers or []); 414 # non-EFI tests can only run on x86 415 platforms = if isEfi then platforms.linux else [ "x86_64-linux" "i686-linux" ]; 416 }; 417 nodes = let 418 commonConfig = { 419 # builds stuff in the VM, needs more juice 420 virtualisation.diskSize = 8 * 1024; 421 virtualisation.cores = 8; 422 virtualisation.memorySize = 2048; 423 424 # both installer and target need to use the same drive 425 virtualisation.diskImage = "./target.qcow2"; 426 427 # and the same TPM options 428 virtualisation.qemu.options = mkIf (clevisTest) [ 429 "-chardev socket,id=chrtpm,path=$NIX_BUILD_TOP/swtpm-sock" 430 "-tpmdev emulator,id=tpm0,chardev=chrtpm" 431 "-device tpm-tis,tpmdev=tpm0" 432 ]; 433 }; 434 in { 435 # The configuration of the system used to run "nixos-install". 436 installer = { 437 imports = [ 438 commonConfig 439 ../modules/profiles/installation-device.nix 440 ../modules/profiles/base.nix 441 extraInstallerConfig 442 ./common/auto-format-root-device.nix 443 ]; 444 445 # In systemdStage1, also automatically format the device backing the 446 # root filesystem. 447 virtualisation.fileSystems."/".autoFormat = systemdStage1; 448 449 boot.initrd.systemd.enable = systemdStage1; 450 451 # Use a small /dev/vdb as the root disk for the 452 # installer. This ensures the target disk (/dev/vda) is 453 # the same during and after installation. 454 virtualisation.emptyDiskImages = [ 512 ]; 455 virtualisation.rootDevice = "/dev/vdb"; 456 457 hardware.enableAllFirmware = mkForce false; 458 459 # The test cannot access the network, so any packages we 460 # need must be included in the VM. 461 system.extraDependencies = with pkgs; [ 462 bintools 463 brotli 464 brotli.dev 465 brotli.lib 466 desktop-file-utils 467 docbook5 468 docbook_xsl_ns 469 kbd.dev 470 kmod.dev 471 libarchive.dev 472 libxml2.bin 473 libxslt.bin 474 nixos-artwork.wallpapers.simple-dark-gray-bottom 475 ntp 476 perlPackages.ListCompare 477 perlPackages.XMLLibXML 478 # make-options-doc/default.nix 479 (python3.withPackages (p: [ p.mistune ])) 480 shared-mime-info 481 sudo 482 texinfo 483 unionfs-fuse 484 xorg.lndir 485 486 # add curl so that rather than seeing the test attempt to download 487 # curl's tarball, we see what it's trying to download 488 curl 489 ] 490 ++ optionals (bootLoader == "grub") (let 491 zfsSupport = extraInstallerConfig.boot.supportedFilesystems.zfs or false; 492 in [ 493 (pkgs.grub2.override { inherit zfsSupport; }) 494 (pkgs.grub2_efi.override { inherit zfsSupport; }) 495 ]) 496 ++ optionals (bootLoader == "systemd-boot") [ 497 pkgs.zstd.bin 498 pkgs.mypy 499 pkgs.bootspec 500 ] 501 ++ optionals clevisTest [ pkgs.klibc ]; 502 503 nix.settings = { 504 substituters = mkForce []; 505 hashed-mirrors = null; 506 connect-timeout = 1; 507 }; 508 }; 509 510 target = { 511 imports = [ commonConfig ]; 512 virtualisation.useBootLoader = true; 513 virtualisation.useEFIBoot = isEfi; 514 virtualisation.useDefaultFilesystems = false; 515 virtualisation.efi.keepVariables = false; 516 517 virtualisation.fileSystems."/" = { 518 device = "/dev/disk/by-label/this-is-not-real-and-will-never-be-used"; 519 fsType = "ext4"; 520 }; 521 }; 522 } // optionalAttrs clevisTest { 523 tang = { 524 services.tang = { 525 enable = true; 526 listenStream = [ "80" ]; 527 ipAddressAllow = [ "192.168.1.0/24" ]; 528 }; 529 networking.firewall.allowedTCPPorts = [ 80 ]; 530 }; 531 }; 532 533 testScript = testScriptFun { 534 inherit bootLoader createPartitions postInstallCommands postBootCommands 535 grubDevice grubIdentifier grubUseEfi extraConfig 536 testSpecialisationConfig testFlakeSwitch clevisTest clevisFallbackTest 537 disableFileSystems; 538 }; 539 }; 540 541 makeLuksRootTest = name: luksFormatOpts: makeInstallerTest name { 542 createPartitions = '' 543 installer.succeed( 544 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 545 + " mkpart primary ext2 1M 100MB" # /boot 546 + " mkpart primary linux-swap 100M 1024M" 547 + " mkpart primary 1024M -1s", # LUKS 548 "udevadm settle", 549 "mkswap /dev/vda2 -L swap", 550 "swapon -L swap", 551 "modprobe dm_mod dm_crypt", 552 "echo -n supersecret | cryptsetup luksFormat ${luksFormatOpts} -q /dev/vda3 -", 553 "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda3 cryptroot", 554 "mkfs.ext3 -L nixos /dev/mapper/cryptroot", 555 "mount LABEL=nixos /mnt", 556 "mkfs.ext3 -L boot /dev/vda1", 557 "mkdir -p /mnt/boot", 558 "mount LABEL=boot /mnt/boot", 559 ) 560 ''; 561 extraConfig = '' 562 boot.kernelParams = lib.mkAfter [ "console=tty0" ]; 563 ''; 564 enableOCR = true; 565 postBootCommands = '' 566 target.wait_for_text("[Pp]assphrase for") 567 target.send_chars("supersecret\n") 568 ''; 569 }; 570 571 # The (almost) simplest partitioning scheme: a swap partition and 572 # one big filesystem partition. 573 simple-test-config = { 574 createPartitions = '' 575 installer.succeed( 576 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 577 + " mkpart primary linux-swap 1M 1024M" 578 + " mkpart primary ext2 1024M -1s", 579 "udevadm settle", 580 "mkswap /dev/vda1 -L swap", 581 "swapon -L swap", 582 "mkfs.ext3 -L nixos /dev/vda2", 583 "mount LABEL=nixos /mnt", 584 ) 585 ''; 586 }; 587 588 simple-test-config-flake = simple-test-config // { 589 testFlakeSwitch = true; 590 }; 591 592 simple-uefi-grub-config = { 593 createPartitions = '' 594 installer.succeed( 595 "flock /dev/vda parted --script /dev/vda -- mklabel gpt" 596 + " mkpart ESP fat32 1M 100MiB" # /boot 597 + " set 1 boot on" 598 + " mkpart primary linux-swap 100MiB 1024MiB" 599 + " mkpart primary ext2 1024MiB -1MiB", # / 600 "udevadm settle", 601 "mkswap /dev/vda2 -L swap", 602 "swapon -L swap", 603 "mkfs.ext3 -L nixos /dev/vda3", 604 "mount LABEL=nixos /mnt", 605 "mkfs.vfat -n BOOT /dev/vda1", 606 "mkdir -p /mnt/boot", 607 "mount LABEL=BOOT /mnt/boot", 608 ) 609 ''; 610 bootLoader = "grub"; 611 grubUseEfi = true; 612 }; 613 614 specialisation-test-extraconfig = { 615 extraConfig = '' 616 environment.systemPackages = [ pkgs.grub2 ]; 617 boot.loader.grub.configurationName = "Home"; 618 specialisation.work.configuration = { 619 boot.loader.grub.configurationName = lib.mkForce "Work"; 620 621 environment.etc = { 622 "gitconfig".text = " 623 [core] 624 gitproxy = none for work.com 625 "; 626 }; 627 }; 628 ''; 629 testSpecialisationConfig = true; 630 }; 631 # disable zfs so we can support latest kernel if needed 632 no-zfs-module = { 633 nixpkgs.overlays = [(final: super: { 634 zfs = super.zfs.overrideAttrs(_: {meta.platforms = [];});} 635 )]; 636 }; 637 638 mkClevisBcachefsTest = { fallback ? false }: makeInstallerTest "clevis-bcachefs${optionalString fallback "-fallback"}" { 639 clevisTest = true; 640 clevisFallbackTest = fallback; 641 enableOCR = fallback; 642 extraInstallerConfig = { 643 imports = [ no-zfs-module ]; 644 boot.supportedFilesystems = [ "bcachefs" ]; 645 environment.systemPackages = with pkgs; [ keyutils clevis ]; 646 }; 647 createPartitions = '' 648 installer.succeed( 649 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 650 + " mkpart primary ext2 1M 100MB" 651 + " mkpart primary linux-swap 100M 1024M" 652 + " mkpart primary 1024M -1s", 653 "udevadm settle", 654 "mkswap /dev/vda2 -L swap", 655 "swapon -L swap", 656 "keyctl link @u @s", 657 "echo -n password | mkfs.bcachefs -L root --encrypted /dev/vda3", 658 "echo -n password | bcachefs unlock /dev/vda3", 659 "echo -n password | mount -t bcachefs /dev/vda3 /mnt", 660 "mkfs.ext3 -L boot /dev/vda1", 661 "mkdir -p /mnt/boot", 662 "mount LABEL=boot /mnt/boot", 663 "udevadm settle") 664 ''; 665 extraConfig = '' 666 boot.initrd.clevis.devices."/dev/vda3".secretFile = "/etc/nixos/clevis-secret.jwe"; 667 668 # We override what nixos-generate-config has generated because we do 669 # not know the UUID in advance. 670 fileSystems."/" = lib.mkForce { device = "/dev/vda3"; fsType = "bcachefs"; }; 671 ''; 672 postBootCommands = optionalString fallback '' 673 target.wait_for_text("enter passphrase for") 674 target.send_chars("password\n") 675 ''; 676 }; 677 678 mkClevisLuksTest = { fallback ? false }: makeInstallerTest "clevis-luks${optionalString fallback "-fallback"}" { 679 clevisTest = true; 680 clevisFallbackTest = fallback; 681 enableOCR = fallback; 682 extraInstallerConfig = { 683 environment.systemPackages = with pkgs; [ clevis ]; 684 }; 685 createPartitions = '' 686 installer.succeed( 687 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 688 + " mkpart primary ext2 1M 100MB" 689 + " mkpart primary linux-swap 100M 1024M" 690 + " mkpart primary 1024M -1s", 691 "udevadm settle", 692 "mkswap /dev/vda2 -L swap", 693 "swapon -L swap", 694 "modprobe dm_mod dm_crypt", 695 "echo -n password | cryptsetup luksFormat -q /dev/vda3 -", 696 "echo -n password | cryptsetup luksOpen --key-file - /dev/vda3 crypt-root", 697 "mkfs.ext3 -L nixos /dev/mapper/crypt-root", 698 "mount LABEL=nixos /mnt", 699 "mkfs.ext3 -L boot /dev/vda1", 700 "mkdir -p /mnt/boot", 701 "mount LABEL=boot /mnt/boot", 702 "udevadm settle") 703 ''; 704 extraConfig = '' 705 boot.initrd.clevis.devices."crypt-root".secretFile = "/etc/nixos/clevis-secret.jwe"; 706 ''; 707 postBootCommands = optionalString fallback '' 708 ${if systemdStage1 then '' 709 target.wait_for_text("Please enter") 710 '' else '' 711 target.wait_for_text("Passphrase for") 712 ''} 713 target.send_chars("password\n") 714 ''; 715 }; 716 717 mkClevisZfsTest = { fallback ? false }: makeInstallerTest "clevis-zfs${optionalString fallback "-fallback"}" { 718 clevisTest = true; 719 clevisFallbackTest = fallback; 720 enableOCR = fallback; 721 extraInstallerConfig = { 722 boot.supportedFilesystems = [ "zfs" ]; 723 environment.systemPackages = with pkgs; [ clevis ]; 724 }; 725 createPartitions = '' 726 installer.succeed( 727 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 728 + " mkpart primary ext2 1M 100MB" 729 + " mkpart primary linux-swap 100M 1024M" 730 + " mkpart primary 1024M -1s", 731 "udevadm settle", 732 "mkswap /dev/vda2 -L swap", 733 "swapon -L swap", 734 "zpool create -O mountpoint=legacy rpool /dev/vda3", 735 "echo -n password | zfs create" 736 + " -o encryption=aes-256-gcm -o keyformat=passphrase rpool/root", 737 "mount -t zfs rpool/root /mnt", 738 "mkfs.ext3 -L boot /dev/vda1", 739 "mkdir -p /mnt/boot", 740 "mount LABEL=boot /mnt/boot", 741 "udevadm settle") 742 ''; 743 extraConfig = '' 744 boot.initrd.clevis.devices."rpool/root".secretFile = "/etc/nixos/clevis-secret.jwe"; 745 boot.zfs.requestEncryptionCredentials = true; 746 747 748 # Using by-uuid overrides the default of by-id, and is unique 749 # to the qemu disks, as they don't produce by-id paths for 750 # some reason. 751 boot.zfs.devNodes = "/dev/disk/by-uuid/"; 752 networking.hostId = "00000000"; 753 ''; 754 postBootCommands = optionalString fallback '' 755 ${if systemdStage1 then '' 756 target.wait_for_text("Enter key for rpool/root") 757 '' else '' 758 target.wait_for_text("Key load error") 759 ''} 760 target.send_chars("password\n") 761 ''; 762 }; 763 764in { 765 766 # !!! `parted mkpart' seems to silently create overlapping partitions. 767 768 769 # The (almost) simplest partitioning scheme: a swap partition and 770 # one big filesystem partition. 771 simple = makeInstallerTest "simple" simple-test-config; 772 773 switchToFlake = makeInstallerTest "switch-to-flake" simple-test-config-flake; 774 775 # Test cloned configurations with the simple grub configuration 776 simpleSpecialised = makeInstallerTest "simpleSpecialised" (simple-test-config // specialisation-test-extraconfig); 777 778 # Simple GPT/UEFI configuration using systemd-boot with 3 partitions: ESP, swap & root filesystem 779 simpleUefiSystemdBoot = makeInstallerTest "simpleUefiSystemdBoot" { 780 createPartitions = '' 781 installer.succeed( 782 "flock /dev/vda parted --script /dev/vda -- mklabel gpt" 783 + " mkpart ESP fat32 1M 100MiB" # /boot 784 + " set 1 boot on" 785 + " mkpart primary linux-swap 100MiB 1024MiB" 786 + " mkpart primary ext2 1024MiB -1MiB", # / 787 "udevadm settle", 788 "mkswap /dev/vda2 -L swap", 789 "swapon -L swap", 790 "mkfs.ext3 -L nixos /dev/vda3", 791 "mount LABEL=nixos /mnt", 792 "mkfs.vfat -n BOOT /dev/vda1", 793 "mkdir -p /mnt/boot", 794 "mount LABEL=BOOT /mnt/boot", 795 ) 796 ''; 797 bootLoader = "systemd-boot"; 798 }; 799 800 simpleUefiGrub = makeInstallerTest "simpleUefiGrub" simple-uefi-grub-config; 801 802 # Test cloned configurations with the uefi grub configuration 803 simpleUefiGrubSpecialisation = makeInstallerTest "simpleUefiGrubSpecialisation" (simple-uefi-grub-config // specialisation-test-extraconfig); 804 805 # Same as the previous, but now with a separate /boot partition. 806 separateBoot = makeInstallerTest "separateBoot" { 807 createPartitions = '' 808 installer.succeed( 809 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 810 + " mkpart primary ext2 1M 100MB" # /boot 811 + " mkpart primary linux-swap 100MB 1024M" 812 + " mkpart primary ext2 1024M -1s", # / 813 "udevadm settle", 814 "mkswap /dev/vda2 -L swap", 815 "swapon -L swap", 816 "mkfs.ext3 -L nixos /dev/vda3", 817 "mount LABEL=nixos /mnt", 818 "mkfs.ext3 -L boot /dev/vda1", 819 "mkdir -p /mnt/boot", 820 "mount LABEL=boot /mnt/boot", 821 ) 822 ''; 823 }; 824 825 # Same as the previous, but with fat32 /boot. 826 separateBootFat = makeInstallerTest "separateBootFat" { 827 createPartitions = '' 828 installer.succeed( 829 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 830 + " mkpart primary ext2 1M 100MB" # /boot 831 + " mkpart primary linux-swap 100MB 1024M" 832 + " mkpart primary ext2 1024M -1s", # / 833 "udevadm settle", 834 "mkswap /dev/vda2 -L swap", 835 "swapon -L swap", 836 "mkfs.ext3 -L nixos /dev/vda3", 837 "mount LABEL=nixos /mnt", 838 "mkfs.vfat -n BOOT /dev/vda1", 839 "mkdir -p /mnt/boot", 840 "mount LABEL=BOOT /mnt/boot", 841 ) 842 ''; 843 }; 844 845 # Same as the previous, but with ZFS /boot. 846 separateBootZfs = makeInstallerTest "separateBootZfs" { 847 extraInstallerConfig = { 848 boot.supportedFilesystems = [ "zfs" ]; 849 }; 850 851 extraConfig = '' 852 # Using by-uuid overrides the default of by-id, and is unique 853 # to the qemu disks, as they don't produce by-id paths for 854 # some reason. 855 boot.zfs.devNodes = "/dev/disk/by-uuid/"; 856 networking.hostId = "00000000"; 857 ''; 858 859 createPartitions = '' 860 installer.succeed( 861 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 862 + " mkpart primary ext2 1M 256MB" # /boot 863 + " mkpart primary linux-swap 256MB 1280M" 864 + " mkpart primary ext2 1280M -1s", # / 865 "udevadm settle", 866 867 "mkswap /dev/vda2 -L swap", 868 "swapon -L swap", 869 870 "mkfs.ext4 -L nixos /dev/vda3", 871 "mount LABEL=nixos /mnt", 872 873 # Use as many ZFS features as possible to verify that GRUB can handle them 874 "zpool create" 875 " -o compatibility=grub2" 876 " -O utf8only=on" 877 " -O normalization=formD" 878 " -O compression=lz4" # Activate the lz4_compress feature 879 " -O xattr=sa" 880 " -O acltype=posixacl" 881 " bpool /dev/vda1", 882 "zfs create" 883 " -o recordsize=1M" # Prepare activating the large_blocks feature 884 " -o mountpoint=legacy" 885 " -o relatime=on" 886 " -o quota=1G" 887 " -o filesystem_limit=100" # Activate the filesystem_limits features 888 " bpool/boot", 889 890 # Snapshotting the top-level dataset would trigger a bug in GRUB2: https://github.com/openzfs/zfs/issues/13873 891 "zfs snapshot bpool/boot@snap-1", # Prepare activating the livelist and bookmarks features 892 "zfs clone bpool/boot@snap-1 bpool/test", # Activate the livelist feature 893 "zfs bookmark bpool/boot@snap-1 bpool/boot#bookmark", # Activate the bookmarks feature 894 "zpool checkpoint bpool", # Activate the zpool_checkpoint feature 895 "mkdir -p /mnt/boot", 896 "mount -t zfs bpool/boot /mnt/boot", 897 "touch /mnt/boot/empty", # Activate zilsaxattr feature 898 "dd if=/dev/urandom of=/mnt/boot/test bs=1M count=1", # Activate the large_blocks feature 899 900 # Print out all enabled and active ZFS features (and some other stuff) 901 "sync /mnt/boot", 902 "zpool get all bpool >&2", 903 904 # Abort early if GRUB2 doesn't like the disks 905 "grub-probe --target=device /mnt/boot >&2", 906 ) 907 ''; 908 909 # umount & export bpool before shutdown 910 # this is a fix for "cannot import 'bpool': pool was previously in use from another system." 911 postInstallCommands = '' 912 installer.succeed("umount /mnt/boot") 913 installer.succeed("zpool export bpool") 914 ''; 915 }; 916 917 # zfs on / with swap 918 zfsroot = makeInstallerTest "zfs-root" { 919 extraInstallerConfig = { 920 boot.supportedFilesystems = [ "zfs" ]; 921 }; 922 923 extraConfig = '' 924 boot.supportedFilesystems = [ "zfs" ]; 925 926 # Using by-uuid overrides the default of by-id, and is unique 927 # to the qemu disks, as they don't produce by-id paths for 928 # some reason. 929 boot.zfs.devNodes = "/dev/disk/by-uuid/"; 930 networking.hostId = "00000000"; 931 ''; 932 933 createPartitions = '' 934 installer.succeed( 935 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 936 + " mkpart primary 1M 100MB" # /boot 937 + " mkpart primary linux-swap 100M 1024M" 938 + " mkpart primary 1024M -1s", # rpool 939 "udevadm settle", 940 "mkswap /dev/vda2 -L swap", 941 "swapon -L swap", 942 "zpool create rpool /dev/vda3", 943 "zfs create -o mountpoint=legacy rpool/root", 944 "mount -t zfs rpool/root /mnt", 945 "zfs create -o mountpoint=legacy rpool/root/usr", 946 "mkdir /mnt/usr", 947 "mount -t zfs rpool/root/usr /mnt/usr", 948 "mkfs.vfat -n BOOT /dev/vda1", 949 "mkdir /mnt/boot", 950 "mount LABEL=BOOT /mnt/boot", 951 "udevadm settle", 952 ) 953 ''; 954 }; 955 956 # Create two physical LVM partitions combined into one volume group 957 # that contains the logical swap and root partitions. 958 lvm = makeInstallerTest "lvm" { 959 createPartitions = '' 960 installer.succeed( 961 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 962 + " mkpart primary 1M 2048M" # PV1 963 + " set 1 lvm on" 964 + " mkpart primary 2048M -1s" # PV2 965 + " set 2 lvm on", 966 "udevadm settle", 967 "pvcreate /dev/vda1 /dev/vda2", 968 "vgcreate MyVolGroup /dev/vda1 /dev/vda2", 969 "lvcreate --size 1G --name swap MyVolGroup", 970 "lvcreate --size 6G --name nixos MyVolGroup", 971 "mkswap -f /dev/MyVolGroup/swap -L swap", 972 "swapon -L swap", 973 "mkfs.xfs -L nixos /dev/MyVolGroup/nixos", 974 "mount LABEL=nixos /mnt", 975 ) 976 ''; 977 extraConfig = optionalString systemdStage1 '' 978 boot.initrd.services.lvm.enable = true; 979 ''; 980 }; 981 982 # Boot off an encrypted root partition with the default LUKS header format 983 luksroot = makeLuksRootTest "luksroot-format1" ""; 984 985 # Boot off an encrypted root partition with LUKS1 format 986 luksroot-format1 = makeLuksRootTest "luksroot-format1" "--type=LUKS1"; 987 988 # Boot off an encrypted root partition with LUKS2 format 989 luksroot-format2 = makeLuksRootTest "luksroot-format2" "--type=LUKS2"; 990 991 # Test whether opening encrypted filesystem with keyfile 992 # Checks for regression of missing cryptsetup, when no luks device without 993 # keyfile is configured 994 encryptedFSWithKeyfile = makeInstallerTest "encryptedFSWithKeyfile" { 995 createPartitions = '' 996 installer.succeed( 997 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 998 + " mkpart primary ext2 1M 100MB" # /boot 999 + " mkpart primary linux-swap 100M 1024M" 1000 + " mkpart primary 1024M 1280M" # LUKS with keyfile 1001 + " mkpart primary 1280M -1s", 1002 "udevadm settle", 1003 "mkswap /dev/vda2 -L swap", 1004 "swapon -L swap", 1005 "mkfs.ext3 -L nixos /dev/vda4", 1006 "mount LABEL=nixos /mnt", 1007 "mkfs.ext3 -L boot /dev/vda1", 1008 "mkdir -p /mnt/boot", 1009 "mount LABEL=boot /mnt/boot", 1010 "modprobe dm_mod dm_crypt", 1011 "echo -n supersecret > /mnt/keyfile", 1012 "cryptsetup luksFormat -q /dev/vda3 --key-file /mnt/keyfile", 1013 "cryptsetup luksOpen --key-file /mnt/keyfile /dev/vda3 crypt", 1014 "mkfs.ext3 -L test /dev/mapper/crypt", 1015 "cryptsetup luksClose crypt", 1016 "mkdir -p /mnt/test", 1017 ) 1018 ''; 1019 extraConfig = '' 1020 fileSystems."/test" = { 1021 device = "/dev/disk/by-label/test"; 1022 fsType = "ext3"; 1023 encrypted.enable = true; 1024 encrypted.blkDev = "/dev/vda3"; 1025 encrypted.label = "crypt"; 1026 encrypted.keyFile = "/${if systemdStage1 then "sysroot" else "mnt-root"}/keyfile"; 1027 }; 1028 ''; 1029 }; 1030 1031 # Full disk encryption (root, kernel and initrd encrypted) using GRUB, GPT/UEFI, 1032 # LVM-on-LUKS and a keyfile in initrd.secrets to enter the passphrase once 1033 fullDiskEncryption = makeInstallerTest "fullDiskEncryption" { 1034 createPartitions = '' 1035 installer.succeed( 1036 "flock /dev/vda parted --script /dev/vda -- mklabel gpt" 1037 + " mkpart ESP fat32 1M 100MiB" # /boot/efi 1038 + " set 1 boot on" 1039 + " mkpart primary ext2 1024MiB -1MiB", # LUKS 1040 "udevadm settle", 1041 "modprobe dm_mod dm_crypt", 1042 "dd if=/dev/random of=luks.key bs=256 count=1", 1043 "echo -n supersecret | cryptsetup luksFormat -q --pbkdf-force-iterations 1000 --type luks1 /dev/vda2 -", 1044 "echo -n supersecret | cryptsetup luksAddKey -q --pbkdf-force-iterations 1000 --key-file - /dev/vda2 luks.key", 1045 "echo -n supersecret | cryptsetup luksOpen --key-file - /dev/vda2 crypt", 1046 "pvcreate /dev/mapper/crypt", 1047 "vgcreate crypt /dev/mapper/crypt", 1048 "lvcreate -L 100M -n swap crypt", 1049 "lvcreate -l '100%FREE' -n nixos crypt", 1050 "mkfs.vfat -n efi /dev/vda1", 1051 "mkfs.ext4 -L nixos /dev/crypt/nixos", 1052 "mkswap -L swap /dev/crypt/swap", 1053 "mount LABEL=nixos /mnt", 1054 "mkdir -p /mnt/{etc/nixos,boot/efi}", 1055 "mount LABEL=efi /mnt/boot/efi", 1056 "swapon -L swap", 1057 "mv luks.key /mnt/etc/nixos/" 1058 ) 1059 ''; 1060 bootLoader = "grub"; 1061 grubUseEfi = true; 1062 extraConfig = '' 1063 boot.loader.grub.enableCryptodisk = true; 1064 boot.loader.efi.efiSysMountPoint = "/boot/efi"; 1065 1066 boot.initrd.secrets."/luks.key" = "/etc/nixos/luks.key"; 1067 boot.initrd.luks.devices.crypt = 1068 { device = "/dev/vda2"; 1069 keyFile = "/luks.key"; 1070 }; 1071 ''; 1072 enableOCR = true; 1073 postBootCommands = '' 1074 target.wait_for_text("Enter passphrase for") 1075 target.send_chars("supersecret\n") 1076 ''; 1077 }; 1078 1079 swraid = makeInstallerTest "swraid" { 1080 createPartitions = '' 1081 installer.succeed( 1082 "flock /dev/vda parted --script /dev/vda --" 1083 + " mklabel msdos" 1084 + " mkpart primary ext2 1M 100MB" # /boot 1085 + " mkpart extended 100M -1s" 1086 + " mkpart logical 102M 3102M" # md0 (root), first device 1087 + " mkpart logical 3103M 6103M" # md0 (root), second device 1088 + " mkpart logical 6104M 6360M" # md1 (swap), first device 1089 + " mkpart logical 6361M 6617M", # md1 (swap), second device 1090 "udevadm settle", 1091 "ls -l /dev/vda* >&2", 1092 "cat /proc/partitions >&2", 1093 "udevadm control --stop-exec-queue", 1094 "mdadm --create --force /dev/md0 --metadata 1.2 --level=raid1 " 1095 + "--raid-devices=2 /dev/vda5 /dev/vda6", 1096 "mdadm --create --force /dev/md1 --metadata 1.2 --level=raid1 " 1097 + "--raid-devices=2 /dev/vda7 /dev/vda8", 1098 "udevadm control --start-exec-queue", 1099 "udevadm settle", 1100 "mkswap -f /dev/md1 -L swap", 1101 "swapon -L swap", 1102 "mkfs.ext3 -L nixos /dev/md0", 1103 "mount LABEL=nixos /mnt", 1104 "mkfs.ext3 -L boot /dev/vda1", 1105 "mkdir /mnt/boot", 1106 "mount LABEL=boot /mnt/boot", 1107 "udevadm settle", 1108 ) 1109 ''; 1110 postBootCommands = '' 1111 target.fail("dmesg | grep 'immediate safe mode'") 1112 ''; 1113 }; 1114 1115 bcache = makeInstallerTest "bcache" { 1116 createPartitions = '' 1117 installer.succeed( 1118 "flock /dev/vda parted --script /dev/vda --" 1119 + " mklabel msdos" 1120 + " mkpart primary ext2 1M 100MB" # /boot 1121 + " mkpart primary 100MB 512MB " # swap 1122 + " mkpart primary 512MB 1024MB" # Cache (typically SSD) 1123 + " mkpart primary 1024MB -1s ", # Backing device (typically HDD) 1124 "modprobe bcache", 1125 "udevadm settle", 1126 "make-bcache -B /dev/vda4 -C /dev/vda3", 1127 "udevadm settle", 1128 "mkfs.ext3 -L nixos /dev/bcache0", 1129 "mount LABEL=nixos /mnt", 1130 "mkfs.ext3 -L boot /dev/vda1", 1131 "mkdir /mnt/boot", 1132 "mount LABEL=boot /mnt/boot", 1133 "mkswap -f /dev/vda2 -L swap", 1134 "swapon -L swap", 1135 ) 1136 ''; 1137 }; 1138 1139 bcachefsSimple = makeInstallerTest "bcachefs-simple" { 1140 extraInstallerConfig = { 1141 boot.supportedFilesystems = [ "bcachefs" ]; 1142 imports = [ no-zfs-module ]; 1143 }; 1144 1145 createPartitions = '' 1146 installer.succeed( 1147 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 1148 + " mkpart primary ext2 1M 100MB" # /boot 1149 + " mkpart primary linux-swap 100M 1024M" # swap 1150 + " mkpart primary 1024M -1s", # / 1151 "udevadm settle", 1152 "mkswap /dev/vda2 -L swap", 1153 "swapon -L swap", 1154 "mkfs.bcachefs -L root /dev/vda3", 1155 "mount -t bcachefs /dev/vda3 /mnt", 1156 "mkfs.ext3 -L boot /dev/vda1", 1157 "mkdir -p /mnt/boot", 1158 "mount /dev/vda1 /mnt/boot", 1159 ) 1160 ''; 1161 }; 1162 1163 bcachefsEncrypted = makeInstallerTest "bcachefs-encrypted" { 1164 extraInstallerConfig = { 1165 boot.supportedFilesystems = [ "bcachefs" ]; 1166 1167 # disable zfs so we can support latest kernel if needed 1168 imports = [ no-zfs-module ]; 1169 1170 environment.systemPackages = with pkgs; [ keyutils ]; 1171 }; 1172 1173 extraConfig = '' 1174 boot.kernelParams = lib.mkAfter [ "console=tty0" ]; 1175 ''; 1176 1177 enableOCR = true; 1178 postBootCommands = '' 1179 # Enter it wrong once 1180 target.wait_for_text("enter passphrase for ") 1181 target.send_chars("wrong\n") 1182 # Then enter it right. 1183 target.wait_for_text("enter passphrase for ") 1184 target.send_chars("password\n") 1185 ''; 1186 1187 createPartitions = '' 1188 installer.succeed( 1189 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 1190 + " mkpart primary ext2 1M 100MB" # /boot 1191 + " mkpart primary linux-swap 100M 1024M" # swap 1192 + " mkpart primary 1024M -1s", # / 1193 "udevadm settle", 1194 "mkswap /dev/vda2 -L swap", 1195 "swapon -L swap", 1196 "echo password | mkfs.bcachefs -L root --encrypted /dev/vda3", 1197 "echo password | bcachefs unlock -k session /dev/vda3", 1198 "echo password | mount -t bcachefs /dev/vda3 /mnt", 1199 "mkfs.ext3 -L boot /dev/vda1", 1200 "mkdir -p /mnt/boot", 1201 "mount /dev/vda1 /mnt/boot", 1202 ) 1203 ''; 1204 }; 1205 1206 bcachefsMulti = makeInstallerTest "bcachefs-multi" { 1207 extraInstallerConfig = { 1208 boot.supportedFilesystems = [ "bcachefs" ]; 1209 1210 # disable zfs so we can support latest kernel if needed 1211 imports = [ no-zfs-module ]; 1212 }; 1213 1214 createPartitions = '' 1215 installer.succeed( 1216 "flock /dev/vda parted --script /dev/vda -- mklabel msdos" 1217 + " mkpart primary ext2 1M 100MB" # /boot 1218 + " mkpart primary linux-swap 100M 1024M" # swap 1219 + " mkpart primary 1024M 4096M" # / 1220 + " mkpart primary 4096M -1s", # / 1221 "udevadm settle", 1222 "mkswap /dev/vda2 -L swap", 1223 "swapon -L swap", 1224 "mkfs.bcachefs -L root --metadata_replicas 2 --foreground_target ssd --promote_target ssd --background_target hdd --label ssd /dev/vda3 --label hdd /dev/vda4", 1225 "mount -t bcachefs /dev/vda3:/dev/vda4 /mnt", 1226 "mkfs.ext3 -L boot /dev/vda1", 1227 "mkdir -p /mnt/boot", 1228 "mount /dev/vda1 /mnt/boot", 1229 ) 1230 ''; 1231 }; 1232 1233 # Test using labels to identify volumes in grub 1234 simpleLabels = makeInstallerTest "simpleLabels" { 1235 createPartitions = '' 1236 installer.succeed( 1237 "sgdisk -Z /dev/vda", 1238 "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", 1239 "mkswap /dev/vda2 -L swap", 1240 "swapon -L swap", 1241 "mkfs.ext4 -L root /dev/vda3", 1242 "mount LABEL=root /mnt", 1243 ) 1244 ''; 1245 grubIdentifier = "label"; 1246 }; 1247 1248 # Test using the provided disk name within grub 1249 # TODO: Fix udev so the symlinks are unneeded in /dev/disks 1250 simpleProvided = makeInstallerTest "simpleProvided" { 1251 createPartitions = '' 1252 uuid = "$(blkid -s UUID -o value /dev/vda2)" 1253 installer.succeed( 1254 "sgdisk -Z /dev/vda", 1255 "sgdisk -n 1:0:+1M -n 2:0:+100M -n 3:0:+1G -N 4 -t 1:ef02 -t 2:8300 " 1256 + "-t 3:8200 -t 4:8300 -c 2:boot -c 4:root /dev/vda", 1257 "mkswap /dev/vda3 -L swap", 1258 "swapon -L swap", 1259 "mkfs.ext4 -L boot /dev/vda2", 1260 "mkfs.ext4 -L root /dev/vda4", 1261 ) 1262 installer.execute(f"ln -s ../../vda2 /dev/disk/by-uuid/{uuid}") 1263 installer.execute("ln -s ../../vda4 /dev/disk/by-label/root") 1264 installer.succeed( 1265 "mount /dev/disk/by-label/root /mnt", 1266 "mkdir /mnt/boot", 1267 f"mount /dev/disk/by-uuid/{uuid} /mnt/boot", 1268 ) 1269 ''; 1270 grubIdentifier = "provided"; 1271 }; 1272 1273 # Simple btrfs grub testing 1274 btrfsSimple = makeInstallerTest "btrfsSimple" { 1275 createPartitions = '' 1276 installer.succeed( 1277 "sgdisk -Z /dev/vda", 1278 "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", 1279 "mkswap /dev/vda2 -L swap", 1280 "swapon -L swap", 1281 "mkfs.btrfs -L root /dev/vda3", 1282 "mount LABEL=root /mnt", 1283 ) 1284 ''; 1285 }; 1286 1287 # Test to see if we can detect /boot and /nix on subvolumes 1288 btrfsSubvols = makeInstallerTest "btrfsSubvols" { 1289 createPartitions = '' 1290 installer.succeed( 1291 "sgdisk -Z /dev/vda", 1292 "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", 1293 "mkswap /dev/vda2 -L swap", 1294 "swapon -L swap", 1295 "mkfs.btrfs -L root /dev/vda3", 1296 "btrfs device scan", 1297 "mount LABEL=root /mnt", 1298 "btrfs subvol create /mnt/boot", 1299 "btrfs subvol create /mnt/nixos", 1300 "btrfs subvol create /mnt/nixos/default", 1301 "umount /mnt", 1302 "mount -o defaults,subvol=nixos/default LABEL=root /mnt", 1303 "mkdir /mnt/boot", 1304 "mount -o defaults,subvol=boot LABEL=root /mnt/boot", 1305 ) 1306 ''; 1307 }; 1308 1309 # Test to see if we can detect default and aux subvolumes correctly 1310 btrfsSubvolDefault = makeInstallerTest "btrfsSubvolDefault" { 1311 createPartitions = '' 1312 installer.succeed( 1313 "sgdisk -Z /dev/vda", 1314 "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", 1315 "mkswap /dev/vda2 -L swap", 1316 "swapon -L swap", 1317 "mkfs.btrfs -L root /dev/vda3", 1318 "btrfs device scan", 1319 "mount LABEL=root /mnt", 1320 "btrfs subvol create /mnt/badpath", 1321 "btrfs subvol create /mnt/badpath/boot", 1322 "btrfs subvol create /mnt/nixos", 1323 "btrfs subvol set-default " 1324 + "$(btrfs subvol list /mnt | grep 'nixos' | awk '{print $2}') /mnt", 1325 "umount /mnt", 1326 "mount -o defaults LABEL=root /mnt", 1327 "mkdir -p /mnt/badpath/boot", # Help ensure the detection mechanism 1328 # is actually looking up subvolumes 1329 "mkdir /mnt/boot", 1330 "mount -o defaults,subvol=badpath/boot LABEL=root /mnt/boot", 1331 ) 1332 ''; 1333 }; 1334 1335 # Test to see if we can deal with subvols that need to be escaped in fstab 1336 btrfsSubvolEscape = makeInstallerTest "btrfsSubvolEscape" { 1337 createPartitions = '' 1338 installer.succeed( 1339 "sgdisk -Z /dev/vda", 1340 "sgdisk -n 1:0:+1M -n 2:0:+1G -N 3 -t 1:ef02 -t 2:8200 -t 3:8300 -c 3:root /dev/vda", 1341 "mkswap /dev/vda2 -L swap", 1342 "swapon -L swap", 1343 "mkfs.btrfs -L root /dev/vda3", 1344 "btrfs device scan", 1345 "mount LABEL=root /mnt", 1346 "btrfs subvol create '/mnt/nixos in space'", 1347 "btrfs subvol create /mnt/boot", 1348 "umount /mnt", 1349 "mount -o 'defaults,subvol=nixos in space' LABEL=root /mnt", 1350 "mkdir /mnt/boot", 1351 "mount -o defaults,subvol=boot LABEL=root /mnt/boot", 1352 ) 1353 ''; 1354 }; 1355} // { 1356 clevisBcachefs = mkClevisBcachefsTest { }; 1357 clevisBcachefsFallback = mkClevisBcachefsTest { fallback = true; }; 1358 clevisLuks = mkClevisLuksTest { }; 1359 clevisLuksFallback = mkClevisLuksTest { fallback = true; }; 1360 clevisZfs = mkClevisZfsTest { }; 1361 clevisZfsFallback = mkClevisZfsTest { fallback = true; }; 1362} // optionalAttrs systemdStage1 { 1363 stratisRoot = makeInstallerTest "stratisRoot" { 1364 createPartitions = '' 1365 installer.succeed( 1366 "sgdisk --zap-all /dev/vda", 1367 "sgdisk --new=1:0:+100M --typecode=0:ef00 /dev/vda", # /boot 1368 "sgdisk --new=2:0:+1G --typecode=0:8200 /dev/vda", # swap 1369 "sgdisk --new=3:0:+5G --typecode=0:8300 /dev/vda", # / 1370 "udevadm settle", 1371 1372 "mkfs.vfat /dev/vda1", 1373 "mkswap /dev/vda2 -L swap", 1374 "swapon -L swap", 1375 "stratis pool create my-pool /dev/vda3", 1376 "stratis filesystem create my-pool nixos", 1377 "udevadm settle", 1378 1379 "mount /dev/stratis/my-pool/nixos /mnt", 1380 "mkdir -p /mnt/boot", 1381 "mount /dev/vda1 /mnt/boot" 1382 ) 1383 ''; 1384 bootLoader = "systemd-boot"; 1385 extraInstallerConfig = { modulesPath, ...}: { 1386 config = { 1387 services.stratis.enable = true; 1388 environment.systemPackages = [ 1389 pkgs.stratis-cli 1390 pkgs.thin-provisioning-tools 1391 pkgs.lvm2.bin 1392 pkgs.stratisd.initrd 1393 ]; 1394 }; 1395 }; 1396 }; 1397 1398 gptAutoRoot = let 1399 rootPartType = { 1400 ia32 = "44479540-F297-41B2-9AF7-D131D5F0458A"; 1401 x64 = "4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709"; 1402 arm = "69DAD710-2CE4-4E3C-B16C-21A1D49ABED3"; 1403 aa64 = "B921B045-1DF0-41C3-AF44-4C6F280D3FAE"; 1404 }.${pkgs.stdenv.hostPlatform.efiArch}; 1405 in makeInstallerTest "gptAutoRoot" { 1406 disableFileSystems = true; 1407 createPartitions = '' 1408 installer.succeed( 1409 "sgdisk --zap-all /dev/vda", 1410 "sgdisk --new=1:0:+100M --typecode=0:ef00 /dev/vda", # /boot 1411 "sgdisk --new=2:0:+1G --typecode=0:8200 /dev/vda", # swap 1412 "sgdisk --new=3:0:+5G --typecode=0:${rootPartType} /dev/vda", # / 1413 "udevadm settle", 1414 1415 "mkfs.vfat /dev/vda1", 1416 "mkswap /dev/vda2 -L swap", 1417 "swapon -L swap", 1418 "mkfs.ext4 -L root /dev/vda3", 1419 "udevadm settle", 1420 1421 "mount /dev/vda3 /mnt", 1422 "mkdir -p /mnt/boot", 1423 "mount /dev/vda1 /mnt/boot" 1424 ) 1425 ''; 1426 bootLoader = "systemd-boot"; 1427 extraConfig = '' 1428 boot.initrd.systemd.root = "gpt-auto"; 1429 boot.initrd.supportedFilesystems = ["ext4"]; 1430 ''; 1431 }; 1432}