1import ./make-test-python.nix ({ lib, ... }: {
2 name = "systemd-initrd-network-ssh";
3 meta.maintainers = [ lib.maintainers.elvishjerricco ];
4
5 nodes = with lib; {
6 server = { config, pkgs, ... }: {
7 environment.systemPackages = [pkgs.cryptsetup];
8 boot.loader.systemd-boot.enable = true;
9 boot.loader.timeout = 0;
10 virtualisation = {
11 emptyDiskImages = [ 4096 ];
12 useBootLoader = true;
13 useEFIBoot = true;
14 };
15
16 specialisation.encrypted-root.configuration = {
17 virtualisation.bootDevice = "/dev/mapper/root";
18 boot.initrd.luks.devices = lib.mkVMOverride {
19 root.device = "/dev/vdc";
20 };
21 boot.initrd.systemd.enable = true;
22 boot.initrd.network = {
23 enable = true;
24 ssh = {
25 enable = true;
26 authorizedKeys = [ (readFile ./initrd-network-ssh/id_ed25519.pub) ];
27 port = 22;
28 # Terrible hack so it works with useBootLoader
29 hostKeys = [ { outPath = "${./initrd-network-ssh/ssh_host_ed25519_key}"; } ];
30 };
31 };
32 };
33 };
34
35 client = { config, ... }: {
36 environment.etc = {
37 knownHosts = {
38 text = concatStrings [
39 "server,"
40 "${
41 toString (head (splitString " " (toString
42 (elemAt (splitString "\n" config.networking.extraHosts) 2))))
43 } "
44 "${readFile ./initrd-network-ssh/ssh_host_ed25519_key.pub}"
45 ];
46 };
47 sshKey = {
48 source = ./initrd-network-ssh/id_ed25519;
49 mode = "0600";
50 };
51 };
52 };
53 };
54
55 testScript = ''
56 start_all()
57
58 def ssh_is_up(_) -> bool:
59 status, _ = client.execute("nc -z server 22")
60 return status == 0
61
62 server.wait_for_unit("multi-user.target")
63 server.succeed(
64 "echo somepass | cryptsetup luksFormat --type=luks2 /dev/vdc",
65 "bootctl set-default nixos-generation-1-specialisation-encrypted-root.conf",
66 "sync",
67 )
68 server.shutdown()
69 server.start()
70
71 client.wait_for_unit("network.target")
72 with client.nested("waiting for SSH server to come up"):
73 retry(ssh_is_up)
74
75 client.succeed(
76 "echo somepass | ssh -i /etc/sshKey -o UserKnownHostsFile=/etc/knownHosts server 'systemd-tty-ask-password-agent' & exit"
77 )
78
79 server.wait_for_unit("multi-user.target")
80 server.succeed("mount | grep '/dev/mapper/root on /'")
81 '';
82})