diff --git a/nixos/modules/services/misc/nix-ssh-serve.nix b/nixos/modules/services/misc/nix-ssh-serve.nix index 66148431709f..5bd9cf9086f1 100644 --- a/nixos/modules/services/misc/nix-ssh-serve.nix +++ b/nixos/modules/services/misc/nix-ssh-serve.nix @@ -1,8 +1,12 @@ { config, lib, pkgs, ... }: with lib; - -{ +let cfg = config.nix.sshServe; + command = + if cfg.protocol == "ssh" + then "nix-store --serve" + else "nix-daemon --stdio"; +in { options = { nix.sshServe = { @@ -10,7 +14,7 @@ with lib; enable = mkOption { type = types.bool; default = false; - description = "Whether to enable serving the Nix store as a binary cache via SSH."; + description = "Whether to enable serving the Nix store as a remote store via SSH."; }; keys = mkOption { @@ -20,14 +24,20 @@ with lib; description = "A list of SSH public keys allowed to access the binary cache via SSH."; }; + protocol = mkOption { + type = types.enum [ "ssh" "ssh-ng" ]; + default = "ssh"; + description = "The specific Nix-over-SSH protocol to use."; + }; + }; }; - config = mkIf config.nix.sshServe.enable { + config = mkIf cfg.enable { users.extraUsers.nix-ssh = { - description = "Nix SSH substituter user"; + description = "Nix SSH store user"; uid = config.ids.uids.nix-ssh; useDefaultShell = true; }; @@ -41,11 +51,11 @@ with lib; PermitTTY no PermitTunnel no X11Forwarding no - ForceCommand ${config.nix.package.out}/bin/nix-store --serve + ForceCommand ${config.nix.package.out}/bin/${command} Match All ''; - users.extraUsers.nix-ssh.openssh.authorizedKeys.keys = config.nix.sshServe.keys; + users.extraUsers.nix-ssh.openssh.authorizedKeys.keys = cfg.keys; }; } diff --git a/nixos/release.nix b/nixos/release.nix index 23f050367d69..558bbbf9a9d4 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -319,6 +319,7 @@ in rec { tests.nfs4 = callTest tests/nfs.nix { version = 4; }; tests.nginx = callTest tests/nginx.nix { }; tests.nghttpx = callTest tests/nghttpx.nix { }; + tests.nix-ssh-serve = callTest tests/nix-ssh-serve.nix { }; tests.novacomd = callTestOnTheseSystems ["x86_64-linux"] tests/novacomd.nix { }; tests.leaps = callTest tests/leaps.nix { }; tests.nsd = callTest tests/nsd.nix {}; diff --git a/nixos/tests/nix-ssh-serve.nix b/nixos/tests/nix-ssh-serve.nix new file mode 100644 index 000000000000..aa366d8612d7 --- /dev/null +++ b/nixos/tests/nix-ssh-serve.nix @@ -0,0 +1,39 @@ +import ./make-test.nix ({ pkgs, lib, ... }: +let inherit (import ./ssh-keys.nix pkgs) + snakeOilPrivateKey snakeOilPublicKey; + ssh-config = builtins.toFile "ssh.conf" '' + UserKnownHostsFile=/dev/null + StrictHostKeyChecking=no + ''; +in + { name = "nix-ssh-serve"; + meta.maintainers = [ lib.maintainers.shlevy ]; + nodes = + { server.nix.sshServe = + { enable = true; + keys = [ snakeOilPublicKey ]; + protocol = "ssh-ng"; + }; + server.nix.package = pkgs.nixUnstable; + client.nix.package = pkgs.nixUnstable; + }; + testScript = '' + startAll; + + $client->succeed("mkdir -m 700 /root/.ssh"); + $client->copyFileFromHost("${ssh-config}", "/root/.ssh/config"); + $client->succeed("cat ${snakeOilPrivateKey} > /root/.ssh/id_ecdsa"); + $client->succeed("chmod 600 /root/.ssh/id_ecdsa"); + + $client->succeed("nix-store --add /etc/machine-id > mach-id-path"); + + $server->waitForUnit("sshd"); + + $client->fail("diff /root/other-store\$(cat mach-id-path) /etc/machine-id"); + # Currently due to shared store this is a noop :( + $client->succeed("nix copy --to ssh-ng://nix-ssh\@server \$(cat mach-id-path)"); + $client->succeed("nix-store --realise \$(cat mach-id-path) --store /root/other-store --substituters ssh-ng://nix-ssh\@server"); + $client->succeed("diff /root/other-store\$(cat mach-id-path) /etc/machine-id"); + ''; + } +) diff --git a/nixos/tests/openssh.nix b/nixos/tests/openssh.nix index 291544996889..b2d254e9d9d9 100644 --- a/nixos/tests/openssh.nix +++ b/nixos/tests/openssh.nix @@ -1,20 +1,7 @@ import ./make-test.nix ({ pkgs, ... }: -let - snakeOilPrivateKey = pkgs.writeText "privkey.snakeoil" '' - -----BEGIN EC PRIVATE KEY----- - MHcCAQEEIHQf/khLvYrQ8IOika5yqtWvI0oquHlpRLTZiJy5dRJmoAoGCCqGSM49 - AwEHoUQDQgAEKF0DYGbBwbj06tA3fd/+yP44cvmwmHBWXZCKbS+RQlAKvLXMWkpN - r1lwMyJZoSGgBHoUahoYjTh9/sJL7XLJtA== - -----END EC PRIVATE KEY----- - ''; - - snakeOilPublicKey = pkgs.lib.concatStrings [ - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA" - "yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa" - "9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil" - ]; - +let inherit (import ./ssh-keys.nix pkgs) + snakeOilPrivateKey snakeOilPublicKey; in { name = "openssh"; meta = with pkgs.stdenv.lib.maintainers; { diff --git a/nixos/tests/ssh-keys.nix b/nixos/tests/ssh-keys.nix new file mode 100644 index 000000000000..07d422196efa --- /dev/null +++ b/nixos/tests/ssh-keys.nix @@ -0,0 +1,15 @@ +pkgs: +{ snakeOilPrivateKey = pkgs.writeText "privkey.snakeoil" '' + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIHQf/khLvYrQ8IOika5yqtWvI0oquHlpRLTZiJy5dRJmoAoGCCqGSM49 + AwEHoUQDQgAEKF0DYGbBwbj06tA3fd/+yP44cvmwmHBWXZCKbS+RQlAKvLXMWkpN + r1lwMyJZoSGgBHoUahoYjTh9/sJL7XLJtA== + -----END EC PRIVATE KEY----- + ''; + + snakeOilPublicKey = pkgs.lib.concatStrings [ + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHA" + "yNTYAAABBBChdA2BmwcG49OrQN33f/sj+OHL5sJhwVl2Qim0vkUJQCry1zFpKTa" + "9ZcDMiWaEhoAR6FGoaGI04ff7CS+1yybQ= sakeoil" + ]; +}