about summary refs log tree commit diff
path: root/nixos/modules/system/boot/initrd-ssh.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/system/boot/initrd-ssh.nix')
-rw-r--r--nixos/modules/system/boot/initrd-ssh.nix64
1 files changed, 54 insertions, 10 deletions
diff --git a/nixos/modules/system/boot/initrd-ssh.nix b/nixos/modules/system/boot/initrd-ssh.nix
index 125f75d667069..60c5ff62ffff0 100644
--- a/nixos/modules/system/boot/initrd-ssh.nix
+++ b/nixos/modules/system/boot/initrd-ssh.nix
@@ -5,6 +5,10 @@ with lib;
 let
 
   cfg = config.boot.initrd.network.ssh;
+  shell = if cfg.shell == null then "/bin/ash" else cfg.shell;
+  inherit (config.programs.ssh) package;
+
+  enabled = let initrd = config.boot.initrd; in (initrd.network.enable || initrd.systemd.network.enable) && cfg.enable;
 
 in
 
@@ -33,8 +37,9 @@ in
     };
 
     shell = mkOption {
-      type = types.str;
-      default = "/bin/ash";
+      type = types.nullOr types.str;
+      default = null;
+      defaultText = ''"/bin/ash"'';
       description = lib.mdDoc ''
         Login shell of the remote user. Can be used to limit actions user can do.
       '';
@@ -119,9 +124,11 @@ in
     sshdCfg = config.services.openssh;
 
     sshdConfig = ''
+      UsePAM no
       Port ${toString cfg.port}
 
       PasswordAuthentication no
+      AuthorizedKeysFile %h/.ssh/authorized_keys %h/.ssh/authorized_keys2 /etc/ssh/authorized_keys.d/%u
       ChallengeResponseAuthentication no
 
       ${flip concatMapStrings cfg.hostKeys (path: ''
@@ -142,7 +149,7 @@ in
 
       ${cfg.extraConfig}
     '';
-  in mkIf (config.boot.initrd.network.enable && cfg.enable) {
+  in mkIf enabled {
     assertions = [
       {
         assertion = cfg.authorizedKeys != [];
@@ -157,14 +164,19 @@ in
           for instructions.
         '';
       }
+
+      {
+        assertion = config.boot.initrd.systemd.enable -> cfg.shell == null;
+        message = "systemd stage 1 does not support boot.initrd.network.ssh.shell";
+      }
     ];
 
-    boot.initrd.extraUtilsCommands = ''
-      copy_bin_and_libs ${pkgs.openssh}/bin/sshd
+    boot.initrd.extraUtilsCommands = mkIf (!config.boot.initrd.systemd.enable) ''
+      copy_bin_and_libs ${package}/bin/sshd
       cp -pv ${pkgs.glibc.out}/lib/libnss_files.so.* $out/lib
     '';
 
-    boot.initrd.extraUtilsCommandsTest = ''
+    boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) ''
       # sshd requires a host key to check config, so we pass in the test's
       tmpkey="$(mktemp initrd-ssh-testkey.XXXXXXXXXX)"
       cp "${../../../tests/initrd-network-ssh/ssh_host_ed25519_key}" "$tmpkey"
@@ -176,9 +188,9 @@ in
       rm "$tmpkey"
     '';
 
-    boot.initrd.network.postCommands = ''
-      echo '${cfg.shell}' > /etc/shells
-      echo 'root:x:0:0:root:/root:${cfg.shell}' > /etc/passwd
+    boot.initrd.network.postCommands = mkIf (!config.boot.initrd.systemd.enable) ''
+      echo '${shell}' > /etc/shells
+      echo 'root:x:0:0:root:/root:${shell}' > /etc/passwd
       echo 'sshd:x:1:1:sshd:/var/empty:/bin/nologin' >> /etc/passwd
       echo 'passwd: files' > /etc/nsswitch.conf
 
@@ -204,7 +216,7 @@ in
       /bin/sshd -e
     '';
 
-    boot.initrd.postMountCommands = ''
+    boot.initrd.postMountCommands = mkIf (!config.boot.initrd.systemd.enable) ''
       # Stop sshd cleanly before stage 2.
       #
       # If you want to keep it around to debug post-mount SSH issues,
@@ -217,6 +229,38 @@ in
 
     boot.initrd.secrets = listToAttrs
       (map (path: nameValuePair (initrdKeyPath path) path) cfg.hostKeys);
+
+    # Systemd initrd stuff
+    boot.initrd.systemd = mkIf config.boot.initrd.systemd.enable {
+      users.sshd = { uid = 1; group = "sshd"; };
+      groups.sshd = { gid = 1; };
+
+      contents."/etc/ssh/authorized_keys.d/root".text =
+        concatStringsSep "\n" config.boot.initrd.network.ssh.authorizedKeys;
+      contents."/etc/ssh/sshd_config".text = sshdConfig;
+      storePaths = ["${package}/bin/sshd"];
+
+      services.sshd = {
+        description = "SSH Daemon";
+        wantedBy = ["initrd.target"];
+        after = ["network.target" "initrd-nixos-copy-secrets.service"];
+
+        # Keys from Nix store are world-readable, which sshd doesn't
+        # like. If this were a real nix store and not the initrd, we
+        # neither would nor could do this
+        preStart = flip concatMapStrings cfg.hostKeys (path: ''
+          /bin/chmod 0600 "${initrdKeyPath path}"
+        '');
+        unitConfig.DefaultDependencies = false;
+        serviceConfig = {
+          ExecStart = "${package}/bin/sshd -D -f /etc/ssh/sshd_config";
+          Type = "simple";
+          KillMode = "process";
+          Restart = "on-failure";
+        };
+      };
+    };
+
   };
 
 }