1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.boot.initrd.network.ssh;
8
9in
10
11{
12
13 options = {
14
15 boot.initrd.network.ssh.enable = mkOption {
16 type = types.bool;
17 default = false;
18 description = ''
19 Start SSH service during initrd boot. It can be used to debug failing
20 boot on a remote server, enter pasphrase for an encrypted partition etc.
21 Service is killed when stage-1 boot is finished.
22 '';
23 };
24
25 boot.initrd.network.ssh.port = mkOption {
26 type = types.int;
27 default = 22;
28 description = ''
29 Port on which SSH initrd service should listen.
30 '';
31 };
32
33 boot.initrd.network.ssh.shell = mkOption {
34 type = types.str;
35 default = "/bin/ash";
36 description = ''
37 Login shell of the remote user. Can be used to limit actions user can do.
38 '';
39 };
40
41 boot.initrd.network.ssh.hostRSAKey = mkOption {
42 type = types.nullOr types.path;
43 default = null;
44 description = ''
45 RSA SSH private key file in the Dropbear format.
46
47 WARNING: This key is contained insecurely in the global Nix store. Do NOT
48 use your regular SSH host private keys for this purpose or you'll expose
49 them to regular users!
50 '';
51 };
52
53 boot.initrd.network.ssh.hostDSSKey = mkOption {
54 type = types.nullOr types.path;
55 default = null;
56 description = ''
57 DSS SSH private key file in the Dropbear format.
58
59 WARNING: This key is contained insecurely in the global Nix store. Do NOT
60 use your regular SSH host private keys for this purpose or you'll expose
61 them to regular users!
62 '';
63 };
64
65 boot.initrd.network.ssh.hostECDSAKey = mkOption {
66 type = types.nullOr types.path;
67 default = null;
68 description = ''
69 ECDSA SSH private key file in the Dropbear format.
70
71 WARNING: This key is contained insecurely in the global Nix store. Do NOT
72 use your regular SSH host private keys for this purpose or you'll expose
73 them to regular users!
74 '';
75 };
76
77 boot.initrd.network.ssh.authorizedKeys = mkOption {
78 type = types.listOf types.str;
79 default = config.users.extraUsers.root.openssh.authorizedKeys.keys;
80 description = ''
81 Authorized keys for the root user on initrd.
82 '';
83 };
84
85 };
86
87 config = mkIf (config.boot.initrd.network.enable && cfg.enable) {
88
89 boot.initrd.extraUtilsCommands = ''
90 copy_bin_and_libs ${pkgs.dropbear}/bin/dropbear
91 cp -pv ${pkgs.glibc}/lib/libnss_files.so.* $out/lib
92 '';
93
94 boot.initrd.extraUtilsCommandsTest = ''
95 $out/bin/dropbear -V
96 '';
97
98 boot.initrd.network.postCommands = ''
99 mkdir /dev/pts
100 mount -t devpts devpts /dev/pts
101
102 echo '${cfg.shell}' > /etc/shells
103 echo 'root:x:0:0:root:/root:${cfg.shell}' > /etc/passwd
104 echo 'passwd: files' > /etc/nsswitch.conf
105
106 mkdir -p /var/log
107 touch /var/log/lastlog
108
109 mkdir -p /etc/dropbear
110 ${optionalString (cfg.hostRSAKey != null) "ln -s ${cfg.hostRSAKey} /etc/dropbear/dropbear_rsa_host_key"}
111 ${optionalString (cfg.hostDSSKey != null) "ln -s ${cfg.hostDSSKey} /etc/dropbear/dropbear_dss_host_key"}
112 ${optionalString (cfg.hostECDSAKey != null) "ln -s ${cfg.hostECDSAKey} /etc/dropbear/dropbear_ecdsa_host_key"}
113
114 mkdir -p /root/.ssh
115 ${concatStrings (map (key: ''
116 echo -n ${escapeShellArg key} >> /root/.ssh/authorized_keys
117 '') cfg.authorizedKeys)}
118
119 dropbear -s -j -k -E -m -p ${toString cfg.port}
120 '';
121
122 };
123
124}