···
else pkgs.buildPackages.openssh;
15
+
# reports boolean as yes / no
16
+
mkValueStringSshd = v:
17
+
if isInt v then toString v
18
+
else if isString v then v
19
+
else if true == v then "yes"
20
+
else if false == v then "no"
21
+
else throw "unsupported type ${typeOf v}: ${(lib.generators.toPretty {}) v}";
23
+
# dont use the "=" operator
24
+
settingsFormat = (pkgs.formats.keyValue {
25
+
mkKeyValue = lib.generators.mkKeyValueDefault {
26
+
mkValueString = mkValueStringSshd;
29
+
configFile = settingsFormat.generate "config" cfg.settings;
sshconf = pkgs.runCommand "sshd.conf-validated" { nativeBuildInputs = [ validationPackage ]; } ''
31
+
cat ${configFile} - >$out <<EOL
···
cfg = config.services.openssh;
cfgc = config.programs.ssh;
nssModulesPath = config.system.nssModules.path;
···
(mkAliasOptionModuleMD [ "services" "sshd" "enable" ] [ "services" "openssh" "enable" ])
(mkAliasOptionModuleMD [ "services" "openssh" "knownHosts" ] [ "programs" "ssh" "knownHosts" ])
(mkRenamedOptionModule [ "services" "openssh" "challengeResponseAuthentication" ] [ "services" "openssh" "kbdInteractiveAuthentication" ])
102
+
(mkRenamedOptionModule [ "services" "openssh" "kbdInteractiveAuthentication" ] [ "services" "openssh" "settings" "KbdInteractiveAuthentication" ])
103
+
(mkRenamedOptionModule [ "services" "openssh" "passwordAuthentication" ] [ "services" "openssh" "settings" "PasswordAuthentication" ])
104
+
(mkRenamedOptionModule [ "services" "openssh" "useDns" ] [ "services" "openssh" "settings" "UseDns" ])
105
+
(mkRenamedOptionModule [ "services" "openssh" "permitRootLogin" ] [ "services" "openssh" "settings" "PermitRootLogin" ])
106
+
(mkRenamedOptionModule [ "services" "openssh" "logLevel" ] [ "services" "openssh" "settings" "LogLevel" ])
···
example = [ "-f AUTHPRIV" "-l INFO" ];
description = lib.mdDoc ''
Commandline flags to add to sftp-server.
148
-
permitRootLogin = mkOption {
149
-
default = "prohibit-password";
150
-
type = types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"];
151
-
description = lib.mdDoc ''
152
-
Whether the root user can login using ssh.
···
213
-
passwordAuthentication = mkOption {
216
-
description = lib.mdDoc ''
217
-
Specifies whether password authentication is allowed.
221
-
kbdInteractiveAuthentication = mkOption {
224
-
description = lib.mdDoc ''
225
-
Specifies whether keyboard-interactive authentication is allowed.
type = types.listOf types.attrs;
···
349
-
logLevel = mkOption {
350
-
type = types.enum [ "QUIET" "FATAL" "ERROR" "INFO" "VERBOSE" "DEBUG" "DEBUG1" "DEBUG2" "DEBUG3" ];
351
-
default = "INFO"; # upstream default
352
-
description = lib.mdDoc ''
353
-
Gives the verbosity level that is used when logging messages from sshd(8). The possible values are:
354
-
QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. The default is INFO. DEBUG and DEBUG1
355
-
are equivalent. DEBUG2 and DEBUG3 each specify higher levels of debugging output. Logging with a DEBUG level
356
-
violates the privacy of users and is not recommended.
360
-
useDns = mkOption {
363
-
description = lib.mdDoc ''
364
-
Specifies whether sshd(8) should look up the remote host name, and to check that the resolved host name for
365
-
the remote IP address maps back to the very same IP address.
366
-
If this option is set to no (the default) then only addresses and not host names may be used in
367
-
~/.ssh/authorized_keys from and sshd_config Match Host directives.
348
+
settings = mkOption {
349
+
description = lib.mdDoc "Verbatim contents of {file}`sshd_config`.";
350
+
example = literalExpression ''{
353
+
type = types.submodule ({name, ...}: {
354
+
freeformType = settingsFormat.type;
356
+
LogLevel = mkOption {
357
+
type = types.enum [ "QUIET" "FATAL" "ERROR" "INFO" "VERBOSE" "DEBUG" "DEBUG1" "DEBUG2" "DEBUG3" ];
358
+
default = "INFO"; # upstream default
359
+
description = lib.mdDoc ''
360
+
Gives the verbosity level that is used when logging messages from sshd(8). Logging with a DEBUG level
361
+
violates the privacy of users and is not recommended.
364
+
UseDns = mkOption {
366
+
# apply if cfg.useDns then "yes" else "no"
368
+
description = lib.mdDoc ''
369
+
Specifies whether sshd(8) should look up the remote host name, and to check that the resolved host name for
370
+
the remote IP address maps back to the very same IP address.
371
+
If this option is set to no (the default) then only addresses and not host names may be used in
372
+
~/.ssh/authorized_keys from and sshd_config Match Host directives.
376
+
PasswordAuthentication = mkOption {
379
+
description = lib.mdDoc ''
380
+
Specifies whether password authentication is allowed.
383
+
PermitRootLogin = mkOption {
384
+
default = "prohibit-password";
385
+
type = types.enum ["yes" "without-password" "prohibit-password" "forced-commands-only" "no"];
386
+
description = lib.mdDoc ''
387
+
Whether the root user can login using ssh.
390
+
KbdInteractiveAuthentication = mkOption {
393
+
description = lib.mdDoc ''
394
+
Specifies whether keyboard-interactive authentication is allowed.
···
security.pam.services.sshd =
499
-
unixAuth = cfg.passwordAuthentication;
529
+
unixAuth = cfg.settings.PasswordAuthentication;
# These values are merged with the ones defined externally, see:
···
Subsystem sftp ${cfg.sftpServerExecutable} ${concatStringsSep " " cfg.sftpFlags}
533
-
PermitRootLogin ${cfg.permitRootLogin}
GatewayPorts ${cfg.gatewayPorts}
535
-
PasswordAuthentication ${if cfg.passwordAuthentication then "yes" else "no"}
536
-
KbdInteractiveAuthentication ${if cfg.kbdInteractiveAuthentication then "yes" else "no"}
PrintMotd no # handled by pam_motd
···
KexAlgorithms ${concatStringsSep "," cfg.kexAlgorithms}
Ciphers ${concatStringsSep "," cfg.ciphers}
MACs ${concatStringsSep "," cfg.macs}
554
-
LogLevel ${cfg.logLevel}
556
-
UseDNS ${if cfg.useDns then "yes" else "no"}
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;