lol

services.openssh: support freeform settings (#193757)

* services.openssh: support freeform settings

Keep "extraConfig" but introduces "settings".

Also renames several options

(mkRenamedOptionModule [ "services" "openssh" "kbdInteractiveAuthentication" ] [ "services" "openssh" "settings" "KbdInteractiveAuthentication" ])
(mkRenamedOptionModule [ "services" "openssh" "passwordAuthentication" ] [ "services" "openssh" "settings" "PasswordAuthentication" ])
(mkRenamedOptionModule [ "services" "openssh" "useDns" ] [ "services" "openssh" "settings" "UseDns" ])
(mkRenamedOptionModule [ "services" "openssh" "permitRootLogin" ] [ "services" "openssh" "settings" "PermitRootLogin" ])

* updated doc
* regen doc

authored by

Matthieu Coudron and committed by
GitHub
cf10d7ae 6dccdc45

+124 -78
+1 -1
nixos/doc/manual/configuration/ssh.section.md
··· 8 8 9 9 By default, root logins using a password are disallowed. They can be 10 10 disabled entirely by setting 11 - [](#opt-services.openssh.permitRootLogin) to `"no"`. 11 + [](#opt-services.openssh.settings.PermitRootLogin) to `"no"`. 12 12 13 13 You can declaratively specify authorised RSA/DSA public keys for a user 14 14 as follows:
+1 -1
nixos/doc/manual/from_md/configuration/ssh.section.xml
··· 9 9 <para> 10 10 By default, root logins using a password are disallowed. They can be 11 11 disabled entirely by setting 12 - <xref linkend="opt-services.openssh.permitRootLogin" /> to 12 + <xref linkend="opt-services.openssh.settings.PermitRootLogin" /> to 13 13 <literal>&quot;no&quot;</literal>. 14 14 </para> 15 15 <para>
+18
nixos/doc/manual/from_md/release-notes/rl-2305.section.xml
··· 326 326 </listitem> 327 327 <listitem> 328 328 <para> 329 + A few openssh options have been moved from extraConfig to the 330 + new freeform option <literal>settings</literal> and renamed as 331 + follow: 332 + <literal>services.openssh.kbdInteractiveAuthentication</literal> 333 + to 334 + <literal>services.openssh.settings.KbdInteractiveAuthentication</literal>, 335 + <literal>services.openssh.passwordAuthentication</literal> to 336 + <literal>services.openssh.settings.PasswordAuthentication</literal>, 337 + <literal>services.openssh.useDns</literal> to 338 + <literal>services.openssh.settings.UseDns</literal>, 339 + <literal>services.openssh.permitRootLogin</literal> to 340 + <literal>services.openssh.settings.PermitRootLogin</literal>, 341 + <literal>services.openssh.logLevel</literal> to 342 + <literal>services.openssh.settings.LogLevel</literal>. 343 + </para> 344 + </listitem> 345 + <listitem> 346 + <para> 329 347 <literal>services.mastodon</literal> gained a tootctl wrapped 330 348 named <literal>mastodon-tootctl</literal> similar to 331 349 <literal>nextcloud-occ</literal> which can be executed from
+2
nixos/doc/manual/release-notes/rl-2305.section.md
··· 85 85 86 86 - The module `usbmuxd` now has the ability to change the package used by the daemon. In case you're experiencing issues with `usbmuxd` you can try an alternative program like `usbmuxd2`. Available as [services.usbmuxd.package](#opt-services.usbmuxd.package) 87 87 88 + - A few openssh options have been moved from extraConfig to the new freeform option `settings` and renamed as follow: `services.openssh.kbdInteractiveAuthentication` to `services.openssh.settings.KbdInteractiveAuthentication`, `services.openssh.passwordAuthentication` to `services.openssh.settings.PasswordAuthentication`, `services.openssh.useDns` to `services.openssh.settings.UseDns`, `services.openssh.permitRootLogin` to `services.openssh.settings.PermitRootLogin`, `services.openssh.logLevel` to `services.openssh.settings.LogLevel`. 89 + 88 90 - `services.mastodon` gained a tootctl wrapped named `mastodon-tootctl` similar to `nextcloud-occ` which can be executed from any user and switches to the configured mastodon user with sudo and sources the environment variables. 89 91 90 92 - The `dnsmasq` service now takes configuration via the
+1 -1
nixos/modules/profiles/installation-device.nix
··· 72 72 # mounting the storage in a different system. 73 73 services.openssh = { 74 74 enable = true; 75 - permitRootLogin = "yes"; 75 + settings.PermitRootLogin = "yes"; 76 76 }; 77 77 78 78 # Enable wpa_supplicant, but don't start it by default.
+75 -53
nixos/modules/services/networking/ssh/sshd.nix
··· 12 12 then cfgc.package 13 13 else pkgs.buildPackages.openssh; 14 14 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}"; 22 + 23 + # dont use the "=" operator 24 + settingsFormat = (pkgs.formats.keyValue { 25 + mkKeyValue = lib.generators.mkKeyValueDefault { 26 + mkValueString = mkValueStringSshd; 27 + } " ";}); 28 + 29 + configFile = settingsFormat.generate "config" cfg.settings; 15 30 sshconf = pkgs.runCommand "sshd.conf-validated" { nativeBuildInputs = [ validationPackage ]; } '' 16 - cat >$out <<EOL 31 + cat ${configFile} - >$out <<EOL 17 32 ${cfg.extraConfig} 18 33 EOL 19 34 ··· 23 38 24 39 cfg = config.services.openssh; 25 40 cfgc = config.programs.ssh; 41 + 26 42 27 43 nssModulesPath = config.system.nssModules.path; 28 44 ··· 82 98 (mkAliasOptionModuleMD [ "services" "sshd" "enable" ] [ "services" "openssh" "enable" ]) 83 99 (mkAliasOptionModuleMD [ "services" "openssh" "knownHosts" ] [ "programs" "ssh" "knownHosts" ]) 84 100 (mkRenamedOptionModule [ "services" "openssh" "challengeResponseAuthentication" ] [ "services" "openssh" "kbdInteractiveAuthentication" ]) 101 + 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" ]) 85 107 ]; 86 108 87 109 ###### interface ··· 142 164 example = [ "-f AUTHPRIV" "-l INFO" ]; 143 165 description = lib.mdDoc '' 144 166 Commandline flags to add to sftp-server. 145 - ''; 146 - }; 147 - 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. 153 167 ''; 154 168 }; 155 169 ··· 210 224 ''; 211 225 }; 212 226 213 - passwordAuthentication = mkOption { 214 - type = types.bool; 215 - default = true; 216 - description = lib.mdDoc '' 217 - Specifies whether password authentication is allowed. 218 - ''; 219 - }; 220 - 221 - kbdInteractiveAuthentication = mkOption { 222 - type = types.bool; 223 - default = true; 224 - description = lib.mdDoc '' 225 - Specifies whether keyboard-interactive authentication is allowed. 226 - ''; 227 - }; 228 - 229 227 hostKeys = mkOption { 230 228 type = types.listOf types.attrs; 231 229 default = ··· 346 344 ''; 347 345 }; 348 346 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. 357 - ''; 358 - }; 359 347 360 - useDns = mkOption { 361 - type = types.bool; 362 - default = false; 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. 368 - ''; 348 + settings = mkOption { 349 + description = lib.mdDoc "Verbatim contents of {file}`sshd_config`."; 350 + example = literalExpression ''{ 351 + UseDns true; 352 + }''; 353 + type = types.submodule ({name, ...}: { 354 + freeformType = settingsFormat.type; 355 + options = { 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. 362 + ''; 363 + }; 364 + UseDns = mkOption { 365 + type = types.bool; 366 + # apply if cfg.useDns then "yes" else "no" 367 + default = false; 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. 373 + ''; 374 + }; 375 + 376 + PasswordAuthentication = mkOption { 377 + type = types.bool; 378 + default = true; 379 + description = lib.mdDoc '' 380 + Specifies whether password authentication is allowed. 381 + ''; 382 + }; 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. 388 + ''; 389 + }; 390 + KbdInteractiveAuthentication = mkOption { 391 + type = types.bool; 392 + default = true; 393 + description = lib.mdDoc '' 394 + Specifies whether keyboard-interactive authentication is allowed. 395 + ''; 396 + }; 397 + }; 398 + }); 369 399 }; 370 400 371 401 extraConfig = mkOption { ··· 496 526 security.pam.services.sshd = 497 527 { startSession = true; 498 528 showMotd = true; 499 - unixAuth = cfg.passwordAuthentication; 529 + unixAuth = cfg.settings.PasswordAuthentication; 500 530 }; 501 531 502 532 # These values are merged with the ones defined externally, see: ··· 530 560 Subsystem sftp ${cfg.sftpServerExecutable} ${concatStringsSep " " cfg.sftpFlags} 531 561 ''} 532 562 533 - PermitRootLogin ${cfg.permitRootLogin} 534 563 GatewayPorts ${cfg.gatewayPorts} 535 - PasswordAuthentication ${if cfg.passwordAuthentication then "yes" else "no"} 536 - KbdInteractiveAuthentication ${if cfg.kbdInteractiveAuthentication then "yes" else "no"} 537 564 538 565 PrintMotd no # handled by pam_motd 539 566 ··· 550 577 KexAlgorithms ${concatStringsSep "," cfg.kexAlgorithms} 551 578 Ciphers ${concatStringsSep "," cfg.ciphers} 552 579 MACs ${concatStringsSep "," cfg.macs} 553 - 554 - LogLevel ${cfg.logLevel} 555 - 556 - UseDNS ${if cfg.useDns then "yes" else "no"} 557 - 558 580 ''; 559 581 560 582 assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
+1 -1
nixos/modules/services/security/fail2ban.nix
··· 339 339 # Block SSH if there are too many failing connection attempts. 340 340 # Benefits from verbose sshd logging to observe failed login attempts, 341 341 # so we set that here unless the user overrode it. 342 - services.openssh.logLevel = lib.mkDefault "VERBOSE"; 342 + services.openssh.settings.LogLevel = lib.mkDefault "VERBOSE"; 343 343 services.fail2ban.jails.sshd = mkDefault '' 344 344 enabled = true 345 345 port = ${concatMapStringsSep "," (p: toString p) config.services.openssh.ports}
+1 -1
nixos/modules/virtualisation/amazon-image.nix
··· 85 85 # Allow root logins only using the SSH key that the user specified 86 86 # at instance creation time. 87 87 services.openssh.enable = true; 88 - services.openssh.permitRootLogin = "prohibit-password"; 88 + services.openssh.settings.PermitRootLogin = "prohibit-password"; 89 89 90 90 # Enable the serial console on ttyS0 91 91 systemd.services."serial-getty@ttyS0".enable = true;
+2 -4
nixos/modules/virtualisation/azure-common.nix
··· 30 30 # Allow root logins only using the SSH key that the user specified 31 31 # at instance creation time, ping client connections to avoid timeouts 32 32 services.openssh.enable = true; 33 - services.openssh.permitRootLogin = "prohibit-password"; 34 - services.openssh.extraConfig = '' 35 - ClientAliveInterval 180 36 - ''; 33 + services.openssh.settings.PermitRootLogin = "prohibit-password"; 34 + services.openssh.settings.ClientAliveInterval = 180; 37 35 38 36 # Force getting the hostname from Azure 39 37 networking.hostName = mkDefault "";
+1 -1
nixos/modules/virtualisation/brightbox-image.nix
··· 103 103 # Allow root logins only using the SSH key that the user specified 104 104 # at instance creation time. 105 105 services.openssh.enable = true; 106 - services.openssh.permitRootLogin = "prohibit-password"; 106 + services.openssh.settings.PermitRootLogin = "prohibit-password"; 107 107 108 108 # Force getting the hostname from Google Compute. 109 109 networking.hostName = mkDefault "";
+1 -1
nixos/modules/virtualisation/cloudstack-config.nix
··· 21 21 # Allow root logins 22 22 services.openssh = { 23 23 enable = true; 24 - permitRootLogin = "prohibit-password"; 24 + settings.PermitRootLogin = "prohibit-password"; 25 25 }; 26 26 27 27 # Cloud-init configuration.
+1 -1
nixos/modules/virtualisation/digital-ocean-config.nix
··· 49 49 }; 50 50 services.openssh = { 51 51 enable = mkDefault true; 52 - passwordAuthentication = mkDefault false; 52 + settings.PasswordAuthentication = mkDefault false; 53 53 }; 54 54 services.do-agent.enable = mkDefault true; 55 55 networking = {
+2 -2
nixos/modules/virtualisation/google-compute-config.nix
··· 29 29 # Allow root logins only using SSH keys 30 30 # and disable password authentication in general 31 31 services.openssh.enable = true; 32 - services.openssh.permitRootLogin = "prohibit-password"; 33 - services.openssh.passwordAuthentication = mkDefault false; 32 + services.openssh.settings.PermitRootLogin = "prohibit-password"; 33 + services.openssh.settings.PasswordAuthentication = mkDefault false; 34 34 35 35 # enable OS Login. This also requires setting enable-oslogin=TRUE metadata on 36 36 # instance or project level
+2 -2
nixos/modules/virtualisation/openstack-config.nix
··· 59 59 # Allow root logins 60 60 services.openssh = { 61 61 enable = true; 62 - permitRootLogin = "prohibit-password"; 63 - passwordAuthentication = mkDefault false; 62 + settings.PermitRootLogin = "prohibit-password"; 63 + settings.PasswordAuthentication = mkDefault false; 64 64 }; 65 65 66 66 users.users.root.initialPassword = "foobar";
+4 -2
nixos/tests/borgbackup.nix
··· 117 117 server = { ... }: { 118 118 services.openssh = { 119 119 enable = true; 120 - passwordAuthentication = false; 121 - kbdInteractiveAuthentication = false; 120 + settings = { 121 + PasswordAuthentication = false; 122 + KbdInteractiveAuthentication = false; 123 + }; 122 124 }; 123 125 124 126 services.borgbackup.repos.repo1 = {
+4 -2
nixos/tests/btrbk.nix
··· 52 52 environment.systemPackages = with pkgs; [ btrfs-progs ]; 53 53 services.openssh = { 54 54 enable = true; 55 - passwordAuthentication = false; 56 - kbdInteractiveAuthentication = false; 55 + settings = { 56 + KbdInteractiveAuthentication = false; 57 + PasswordAuthentication = false; 58 + }; 57 59 }; 58 60 services.btrbk = { 59 61 extraPackages = [ pkgs.lz4 ];
+2 -2
nixos/tests/google-oslogin/server.nix
··· 17 17 }; 18 18 19 19 services.openssh.enable = true; 20 - services.openssh.kbdInteractiveAuthentication = false; 21 - services.openssh.passwordAuthentication = false; 20 + services.openssh.settings.KbdInteractiveAuthentication = false; 21 + services.openssh.settings.PasswordAuthentication = false; 22 22 23 23 security.googleOsLogin.enable = true; 24 24
+4 -2
nixos/tests/sourcehut.nix
··· 18 18 # passwordless ssh server 19 19 services.openssh = { 20 20 enable = true; 21 - permitRootLogin = "yes"; 22 - extraConfig = "PermitEmptyPasswords yes"; 21 + settings = { 22 + PermitRootLogin = "yes"; 23 + PermitEmptyPasswords = true; 24 + }; 23 25 }; 24 26 25 27 users = {
+1 -1
nixos/tests/turbovnc-headless-server.nix
··· 26 26 # So that we can ssh into the VM, see e.g. 27 27 # http://blog.patapon.info/nixos-local-vm/#accessing-the-vm-with-ssh 28 28 services.openssh.enable = true; 29 - services.openssh.permitRootLogin = "yes"; 29 + services.openssh.settings.PermitRootLogin = "yes"; 30 30 users.extraUsers.root.password = ""; 31 31 users.mutableUsers = false; 32 32 };