0bdba6c99b
This change removes the bespoke logic around identifying block devices. Instead of trying to find the right device by iterating over `qemu.drives` and guessing the right partition number (e.g. /dev/vda{1,2}), devices are now identified by persistent names provided by udev in /dev/disk/by-*. Before this change, the root device was formatted on demand in the initrd. However, this makes it impossible to use filesystem identifiers to identify devices. Now, the formatting step is performed before the VM is started. Because some tests, however, rely on this behaviour, a utility function to replace this behaviour in added in /nixos/tests/common/auto-format-root-device.nix. Devices that contain neither a partition table nor a filesystem are identified by their hardware serial number which is injecetd via QEMU (and is thus persistent and predictable). PCI paths are not a reliably way to identify devices because their availability and numbering depends on the QEMU machine type. This change makes the module more robust against changes in QEMU and the kernel (non-persistent device naming) and by decoupling abstractions (i.e. rootDevice, bootPartition, and bootLoaderDevice) enables further improvement down the line.
86 lines
2.6 KiB
Nix
86 lines
2.6 KiB
Nix
import ./make-test-python.nix ({ lib, ... }: {
|
|
name = "systemd-initrd-network-ssh";
|
|
meta.maintainers = [ lib.maintainers.elvishjerricco ];
|
|
|
|
nodes = with lib; {
|
|
server = { config, pkgs, ... }: {
|
|
environment.systemPackages = [pkgs.cryptsetup];
|
|
boot.loader.systemd-boot.enable = true;
|
|
boot.loader.timeout = 0;
|
|
virtualisation = {
|
|
emptyDiskImages = [ 4096 ];
|
|
useBootLoader = true;
|
|
# Booting off the encrypted disk requires an available init script from the Nix store
|
|
mountHostNixStore = true;
|
|
useEFIBoot = true;
|
|
};
|
|
|
|
specialisation.encrypted-root.configuration = {
|
|
virtualisation.rootDevice = "/dev/mapper/root";
|
|
virtualisation.fileSystems."/".autoFormat = true;
|
|
boot.initrd.luks.devices = lib.mkVMOverride {
|
|
root.device = "/dev/vdb";
|
|
};
|
|
boot.initrd.systemd.enable = true;
|
|
boot.initrd.network = {
|
|
enable = true;
|
|
ssh = {
|
|
enable = true;
|
|
authorizedKeys = [ (readFile ./initrd-network-ssh/id_ed25519.pub) ];
|
|
port = 22;
|
|
# Terrible hack so it works with useBootLoader
|
|
hostKeys = [ { outPath = "${./initrd-network-ssh/ssh_host_ed25519_key}"; } ];
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
client = { config, ... }: {
|
|
environment.etc = {
|
|
knownHosts = {
|
|
text = concatStrings [
|
|
"server,"
|
|
"${
|
|
toString (head (splitString " " (toString
|
|
(elemAt (splitString "\n" config.networking.extraHosts) 2))))
|
|
} "
|
|
"${readFile ./initrd-network-ssh/ssh_host_ed25519_key.pub}"
|
|
];
|
|
};
|
|
sshKey = {
|
|
source = ./initrd-network-ssh/id_ed25519;
|
|
mode = "0600";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
testScript = ''
|
|
start_all()
|
|
|
|
def ssh_is_up(_) -> bool:
|
|
status, _ = client.execute("nc -z server 22")
|
|
return status == 0
|
|
|
|
server.wait_for_unit("multi-user.target")
|
|
server.succeed(
|
|
"echo somepass | cryptsetup luksFormat --type=luks2 /dev/vdb",
|
|
"bootctl set-default nixos-generation-1-specialisation-encrypted-root.conf",
|
|
"sync",
|
|
)
|
|
server.shutdown()
|
|
server.start()
|
|
|
|
client.wait_for_unit("network.target")
|
|
with client.nested("waiting for SSH server to come up"):
|
|
retry(ssh_is_up)
|
|
|
|
client.succeed(
|
|
"echo somepass | ssh -i /etc/sshKey -o UserKnownHostsFile=/etc/knownHosts server 'systemd-tty-ask-password-agent' & exit"
|
|
)
|
|
|
|
server.wait_for_unit("multi-user.target")
|
|
server.succeed("mount | grep '/dev/mapper/root on /'")
|
|
'';
|
|
})
|