at master 7.2 kB view raw
1{ 2 hostPkgs, 3 lib, 4 withNg, 5 ... 6}: 7{ 8 name = "nixos-rebuild-target-host"; 9 10 # TODO: remove overlay from nixos/modules/profiles/installation-device.nix 11 # make it a _small package instead, then remove pkgsReadOnly = false;. 12 node.pkgsReadOnly = false; 13 14 nodes = { 15 deployer = 16 { lib, pkgs, ... }: 17 let 18 inherit (import ./ssh-keys.nix pkgs) snakeOilPrivateKey snakeOilPublicKey; 19 in 20 { 21 imports = [ ../modules/profiles/installation-device.nix ]; 22 23 nix.settings = { 24 substituters = lib.mkForce [ ]; 25 hashed-mirrors = null; 26 connect-timeout = 1; 27 }; 28 29 environment.systemPackages = [ pkgs.passh ]; 30 31 system.includeBuildDependencies = true; 32 33 virtualisation = { 34 cores = 2; 35 memorySize = 2048; 36 }; 37 38 system.build.privateKey = snakeOilPrivateKey; 39 system.build.publicKey = snakeOilPublicKey; 40 # We don't switch on `deployer`, but we need it to have the dependencies 41 # available, to be picked up by system.includeBuildDependencies above. 42 system.rebuild.enableNg = withNg; 43 system.switch.enable = true; 44 }; 45 46 target = 47 { nodes, lib, ... }: 48 let 49 targetConfig = { 50 documentation.enable = false; 51 services.openssh.enable = true; 52 53 users.users.root.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ]; 54 users.users.alice.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ]; 55 users.users.bob.openssh.authorizedKeys.keys = [ nodes.deployer.system.build.publicKey ]; 56 57 users.users.alice.extraGroups = [ "wheel" ]; 58 users.users.bob.extraGroups = [ "wheel" ]; 59 60 # Disable sudo for root to ensure sudo isn't called without `--sudo` 61 security.sudo.extraRules = lib.mkForce [ 62 { 63 groups = [ "wheel" ]; 64 commands = [ { command = "ALL"; } ]; 65 } 66 { 67 users = [ "alice" ]; 68 commands = [ 69 { 70 command = "ALL"; 71 options = [ "NOPASSWD" ]; 72 } 73 ]; 74 } 75 ]; 76 77 nix.settings.trusted-users = [ "@wheel" ]; 78 }; 79 in 80 { 81 imports = [ ./common/user-account.nix ]; 82 83 config = lib.mkMerge [ 84 targetConfig 85 { 86 system.build = { 87 inherit targetConfig; 88 }; 89 system.switch.enable = true; 90 91 networking.hostName = "target"; 92 } 93 ]; 94 }; 95 }; 96 97 testScript = 98 { nodes, ... }: 99 let 100 sshConfig = builtins.toFile "ssh.conf" '' 101 UserKnownHostsFile=/dev/null 102 StrictHostKeyChecking=no 103 ''; 104 105 targetConfigJSON = hostPkgs.writeText "target-configuration.json" ( 106 builtins.toJSON nodes.target.system.build.targetConfig 107 ); 108 109 targetNetworkJSON = hostPkgs.writeText "target-network.json" ( 110 builtins.toJSON nodes.target.system.build.networkConfig 111 ); 112 113 configFile = 114 hostname: 115 hostPkgs.writeText "configuration.nix" # nix 116 '' 117 { lib, modulesPath, ... }: { 118 imports = [ 119 (modulesPath + "/virtualisation/qemu-vm.nix") 120 (modulesPath + "/testing/test-instrumentation.nix") 121 (modulesPath + "/../tests/common/user-account.nix") 122 (lib.modules.importJSON ./target-configuration.json) 123 (lib.modules.importJSON ./target-network.json) 124 ./hardware-configuration.nix 125 ]; 126 127 boot.loader.grub = { 128 enable = true; 129 device = "/dev/vda"; 130 forceInstall = true; 131 }; 132 133 system.rebuild.enableNg = ${lib.boolToString withNg}; 134 135 ${lib.optionalString withNg # nix 136 '' 137 nixpkgs.overlays = [ 138 (final: prev: { 139 # Set tmpdir inside nixos-rebuild-ng to test 140 # "Deploy works with very long TMPDIR" 141 nixos-rebuild-ng = prev.nixos-rebuild-ng.override { withTmpdir = "/tmp"; }; 142 }) 143 ]; 144 '' 145 } 146 147 # this will be asserted 148 networking.hostName = "${hostname}"; 149 } 150 ''; 151 in 152 # python 153 '' 154 start_all() 155 target.wait_for_open_port(22) 156 157 deployer.wait_until_succeeds("ping -c1 target") 158 deployer.succeed("install -Dm 600 ${nodes.deployer.system.build.privateKey} ~root/.ssh/id_ecdsa") 159 deployer.succeed("install ${sshConfig} ~root/.ssh/config") 160 161 target.succeed("nixos-generate-config") 162 deployer.succeed("scp alice@target:/etc/nixos/hardware-configuration.nix /root/hardware-configuration.nix") 163 164 deployer.copy_from_host("${configFile "config-1-deployed"}", "/root/configuration-1.nix") 165 deployer.copy_from_host("${configFile "config-2-deployed"}", "/root/configuration-2.nix") 166 deployer.copy_from_host("${configFile "config-3-deployed"}", "/root/configuration-3.nix") 167 deployer.copy_from_host("${targetNetworkJSON}", "/root/target-network.json") 168 deployer.copy_from_host("${targetConfigJSON}", "/root/target-configuration.json") 169 170 # Ensure sudo is disabled for root 171 target.fail("sudo true") 172 173 # This test also ensures that sudo is not called without --sudo 174 with subtest("Deploy to root@target"): 175 deployer.succeed("nixos-rebuild switch -I nixos-config=/root/configuration-1.nix --target-host root@target &>/dev/console") 176 target_hostname = deployer.succeed("ssh alice@target cat /etc/hostname").rstrip() 177 assert target_hostname == "config-1-deployed", f"{target_hostname=}" 178 179 with subtest("Deploy to alice@target with passwordless sudo"): 180 deployer.succeed("nixos-rebuild switch -I nixos-config=/root/configuration-2.nix --target-host alice@target --sudo &>/dev/console") 181 target_hostname = deployer.succeed("ssh alice@target cat /etc/hostname").rstrip() 182 assert target_hostname == "config-2-deployed", f"{target_hostname=}" 183 184 with subtest("Deploy to bob@target with password based sudo"): 185 # TODO: investigate why --ask-sudo-password from nixos-rebuild-ng is not working here 186 deployer.succeed(r'${lib.optionalString withNg "NIX_SSHOPTS=-t "}passh -c 3 -C -p ${nodes.target.users.users.bob.password} -P "\[sudo\] password" nixos-rebuild switch -I nixos-config=/root/configuration-3.nix --target-host bob@target --sudo &>/dev/console') 187 target_hostname = deployer.succeed("ssh alice@target cat /etc/hostname").rstrip() 188 assert target_hostname == "config-3-deployed", f"{target_hostname=}" 189 190 with subtest("Deploy works with very long TMPDIR"): 191 tmp_dir = "/var/folder/veryveryveryveryverylongpathnamethatdoesnotworkwithcontrolpath" 192 deployer.succeed(f"mkdir -p {tmp_dir}") 193 deployer.succeed(f"TMPDIR={tmp_dir} nixos-rebuild switch -I nixos-config=/root/configuration-1.nix --target-host root@target &>/dev/console") 194 ''; 195}