diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix
index d3183f7d2dc..e9ad47adec9 100644
--- a/nixos/modules/programs/ssh.nix
+++ b/nixos/modules/programs/ssh.nix
@@ -18,6 +18,14 @@ let
exec ${askPassword}
'';
+ knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
+
+ knownHostsText = flip (concatMapStringsSep "\n") knownHosts
+ (h:
+ concatStringsSep "," h.hostNames + " "
+ + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
+ );
+
in
{
###### interface
@@ -92,16 +100,72 @@ in
'';
};
+ knownHosts = mkOption {
+ default = {};
+ type = types.loaOf types.optionSet;
+ description = ''
+ The set of system-wide known SSH hosts.
+ '';
+ example = [
+ {
+ hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
+ publicKeyFile = literalExample "./pubkeys/myhost_ssh_host_dsa_key.pub";
+ }
+ {
+ hostNames = [ "myhost2" ];
+ publicKeyFile = literalExample "./pubkeys/myhost2_ssh_host_dsa_key.pub";
+ }
+ ];
+ options = {
+ hostNames = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ description = ''
+ A list of host names and/or IP numbers used for accessing
+ the host's ssh service.
+ '';
+ };
+ publicKey = mkOption {
+ default = null;
+ type = types.nullOr types.str;
+ example = "ecdsa-sha2-nistp521 AAAAE2VjZHN...UEPg==";
+ description = ''
+ The public key data for the host. You can fetch a public key
+ from a running SSH server with the ssh-keyscan
+ command. The public key should not include any host names, only
+ the key type and the key itself.
+ '';
+ };
+ publicKeyFile = mkOption {
+ default = null;
+ type = types.nullOr types.path;
+ description = ''
+ The path to the public key file for the host. The public
+ key file is read at build time and saved in the Nix store.
+ You can fetch a public key file from a running SSH server
+ with the ssh-keyscan command. The content
+ of the file should follow the same format as described for
+ the publicKey option.
+ '';
+ };
+ };
+ };
+
};
};
config = {
- assertions = singleton
- { assertion = cfg.forwardX11 -> cfg.setXAuthLocation;
- message = "cannot enable X11 forwarding without setting XAuth location";
- };
+ assertions =
+ [ { assertion = cfg.forwardX11 -> cfg.setXAuthLocation;
+ message = "cannot enable X11 forwarding without setting XAuth location";
+ }
+ ] ++ flip mapAttrsToList cfg.knownHosts (name: data: {
+ assertion = (data.publicKey == null && data.publicKeyFile != null) ||
+ (data.publicKey != null && data.publicKeyFile == null);
+ message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
+ });
# SSH configuration. Slight duplication of the sshd_config
# generation in the sshd service.
@@ -118,6 +182,8 @@ in
${cfg.extraConfig}
'';
+ environment.etc."ssh/ssh_known_hosts".text = knownHostsText;
+
# FIXME: this should really be socket-activated for über-awesomeness.
systemd.user.services.ssh-agent =
{ enable = cfg.startAgent;
diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix
index 4db08b7ad3d..6f7dcb837a0 100644
--- a/nixos/modules/rename.nix
+++ b/nixos/modules/rename.nix
@@ -110,6 +110,7 @@ in zipModules ([]
++ obsolete [ "services" "sshd" "permitRootLogin" ] [ "services" "openssh" "permitRootLogin" ]
++ obsolete [ "services" "xserver" "startSSHAgent" ] [ "services" "xserver" "startOpenSSHAgent" ]
++ obsolete [ "services" "xserver" "startOpenSSHAgent" ] [ "programs" "ssh" "startAgent" ]
+++ alias [ "services" "openssh" "knownHosts" ] [ "programs" "ssh" "knownHosts" ]
# VirtualBox
++ obsolete [ "services" "virtualbox" "enable" ] [ "virtualisation" "virtualbox" "guest" "enable" ]
diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix
index 1c428ceddfd..4c7e4d8d088 100644
--- a/nixos/modules/services/networking/ssh/sshd.nix
+++ b/nixos/modules/services/networking/ssh/sshd.nix
@@ -9,14 +9,6 @@ let
nssModulesPath = config.system.nssModules.path;
- knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
-
- knownHostsText = flip (concatMapStringsSep "\n") knownHosts
- (h:
- concatStringsSep "," h.hostNames + " "
- + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
- );
-
userOptions = {
openssh.authorizedKeys = {
@@ -48,8 +40,7 @@ let
};
authKeysFiles = let
- mkAuthKeyFile = u: {
- target = "ssh/authorized_keys.d/${u.name}";
+ mkAuthKeyFile = u: nameValuePair "ssh/authorized_keys.d/${u.name}" {
mode = "0444";
source = pkgs.writeText "${u.name}-authorized_keys" ''
${concatStringsSep "\n" u.openssh.authorizedKeys.keys}
@@ -59,7 +50,7 @@ let
usersWithKeys = attrValues (flip filterAttrs config.users.extraUsers (n: u:
length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0
));
- in map mkAuthKeyFile usersWithKeys;
+ in listToAttrs (map mkAuthKeyFile usersWithKeys);
in
@@ -211,57 +202,6 @@ in
description = "Verbatim contents of sshd_config.";
};
- knownHosts = mkOption {
- default = {};
- type = types.loaOf types.optionSet;
- description = ''
- The set of system-wide known SSH hosts.
- '';
- example = [
- {
- hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
- publicKeyFile = literalExample "./pubkeys/myhost_ssh_host_dsa_key.pub";
- }
- {
- hostNames = [ "myhost2" ];
- publicKeyFile = literalExample "./pubkeys/myhost2_ssh_host_dsa_key.pub";
- }
- ];
- options = {
- hostNames = mkOption {
- type = types.listOf types.str;
- default = [];
- description = ''
- A list of host names and/or IP numbers used for accessing
- the host's ssh service.
- '';
- };
- publicKey = mkOption {
- default = null;
- type = types.nullOr types.str;
- example = "ecdsa-sha2-nistp521 AAAAE2VjZHN...UEPg==";
- description = ''
- The public key data for the host. You can fetch a public key
- from a running SSH server with the ssh-keyscan
- command. The public key should not include any host names, only
- the key type and the key itself.
- '';
- };
- publicKeyFile = mkOption {
- default = null;
- type = types.nullOr types.path;
- description = ''
- The path to the public key file for the host. The public
- key file is read at build time and saved in the Nix store.
- You can fetch a public key file from a running SSH server
- with the ssh-keyscan command. The content
- of the file should follow the same format as described for
- the publicKey option.
- '';
- };
- };
- };
-
moduliFile = mkOption {
example = "services.openssh.moduliFile = /etc/my-local-ssh-moduli;";
type = types.path;
@@ -292,14 +232,8 @@ in
services.openssh.moduliFile = mkDefault "${cfgc.package}/etc/ssh/moduli";
- environment.etc = authKeysFiles ++ [
- { source = cfg.moduliFile;
- target = "ssh/moduli";
- }
- { text = knownHostsText;
- target = "ssh/ssh_known_hosts";
- }
- ];
+ environment.etc = authKeysFiles //
+ { "ssh/moduli".source = cfg.moduliFile; };
systemd =
let
@@ -417,11 +351,6 @@ in
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
message = "cannot enable X11 forwarding without setting xauth location";}]
- ++ flip mapAttrsToList cfg.knownHosts (name: data: {
- assertion = (data.publicKey == null && data.publicKeyFile != null) ||
- (data.publicKey != null && data.publicKeyFile == null);
- message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
- })
++ flip map cfg.listenAddresses ({ addr, port, ... }: {
assertion = addr != null;
message = "addr must be specified in each listenAddresses entry";