1 { config, lib, pkgs, ... }:
9 cfg = config.services.lshd;
24 description = lib.mdDoc ''
25 Whether to enable the GNU lshd SSH2 daemon, which allows
30 portNumber = mkOption {
33 description = lib.mdDoc ''
34 The port on which to listen for connections.
38 interfaces = mkOption {
40 type = types.listOf types.str;
41 description = lib.mdDoc ''
42 List of network interfaces where listening for connections.
43 When providing the empty list, `[]', lshd listens on all
46 example = [ "localhost" "1.2.3.4:443" ];
50 default = "/etc/lsh/host-key";
52 description = lib.mdDoc ''
53 Path to the server's private key. Note that this key must
54 have been created, e.g., using "lsh-keygen --server |
55 lsh-writekey --server", so that you can run lshd.
62 description = lib.mdDoc "Whether to enable syslog output.";
65 passwordAuthentication = mkOption {
68 description = lib.mdDoc "Whether to enable password authentication.";
71 publicKeyAuthentication = mkOption {
74 description = lib.mdDoc "Whether to enable public key authentication.";
77 rootLogin = mkOption {
80 description = lib.mdDoc "Whether to enable remote root login.";
83 loginShell = mkOption {
85 type = types.nullOr types.str;
86 description = lib.mdDoc ''
87 If non-null, override the default login shell with the
90 example = "/nix/store/xyz-bash-10.0/bin/bash10";
93 srpKeyExchange = mkOption {
96 description = lib.mdDoc ''
97 Whether to enable SRP key exchange and user authentication.
101 tcpForwarding = mkOption {
104 description = lib.mdDoc "Whether to enable TCP/IP forwarding.";
107 x11Forwarding = mkOption {
110 description = lib.mdDoc "Whether to enable X11 forwarding.";
113 subsystems = mkOption {
114 type = types.listOf types.path;
115 description = lib.mdDoc ''
116 List of subsystem-path pairs, where the head of the pair
117 denotes the subsystem name, and the tail denotes the path to
118 an executable implementing it.
127 ###### implementation
129 config = mkIf cfg.enable {
131 services.lshd.subsystems = [ ["sftp" "${pkgs.lsh}/sbin/sftp-server"] ];
133 systemd.services.lshd = {
134 description = "GNU lshd SSH2 daemon";
136 after = [ "network.target" ];
138 wantedBy = [ "multi-user.target" ];
141 LD_LIBRARY_PATH = config.system.nssModules.path;
145 test -d /etc/lsh || mkdir -m 0755 -p /etc/lsh
146 test -d /var/spool/lsh || mkdir -m 0755 -p /var/spool/lsh
148 if ! test -f /var/spool/lsh/yarrow-seed-file
150 # XXX: It would be nice to provide feedback to the
151 # user when this fails, so that they can retry it
153 ${lsh}/bin/lsh-make-seed --sloppy \
154 -o /var/spool/lsh/yarrow-seed-file
157 if ! test -f "${cfg.hostKey}"
159 ${lsh}/bin/lsh-keygen --server | \
160 ${lsh}/bin/lsh-writekey --server -o "${cfg.hostKey}"
164 script = with cfg; ''
165 ${lsh}/sbin/lshd --daemonic \
166 --password-helper="${lsh}/sbin/lsh-pam-checkpw" \
167 -p ${toString portNumber} \
168 ${if interfaces == [] then ""
169 else (concatStrings (map (i: "--interface=\"${i}\"")
172 ${if !syslog then "--no-syslog" else ""} \
173 ${if passwordAuthentication then "--password" else "--no-password" } \
174 ${if publicKeyAuthentication then "--publickey" else "--no-publickey" } \
175 ${if rootLogin then "--root-login" else "--no-root-login" } \
176 ${if loginShell != null then "--login-shell=\"${loginShell}\"" else "" } \
177 ${if srpKeyExchange then "--srp-keyexchange" else "--no-srp-keyexchange" } \
178 ${if !tcpForwarding then "--no-tcpip-forward" else "--tcpip-forward"} \
179 ${if x11Forwarding then "--x11-forward" else "--no-x11-forward" } \
180 --subsystems=${concatStringsSep ","
181 (map (pair: (head pair) + "=" +
187 security.pam.services.lshd = {};