summaryrefslogtreecommitdiff
path: root/modules/programs/ssh
diff options
context:
space:
mode:
authorDaiderd Jordan <daiderd@gmail.com>2018-03-06 20:42:33 +0100
committerDaiderd Jordan <daiderd@gmail.com>2018-03-06 20:42:33 +0100
commit2b721afd999a4515327856a8243647fcca826353 (patch)
tree03c1ecf606e66eb036b8fe8244a0e902eca87523 /modules/programs/ssh
parent84a3fcadd06c35a91eb84a5739452c53be55d8ea (diff)
ssh: add option to configure known hosts
Diffstat (limited to 'modules/programs/ssh')
-rw-r--r--modules/programs/ssh/default.nix91
1 files changed, 91 insertions, 0 deletions
diff --git a/modules/programs/ssh/default.nix b/modules/programs/ssh/default.nix
new file mode 100644
index 0000000..2a15a8b
--- /dev/null
+++ b/modules/programs/ssh/default.nix
@@ -0,0 +1,91 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.programs.ssh;
+
+ knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
+
+ host =
+ { name, ... }:
+ {
+ 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 <command>ssh-keyscan</command>
+ 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 <command>ssh-keyscan</command> command. The content
+ of the file should follow the same format as described for
+ the <literal>publicKey</literal> option.
+ '';
+ };
+ };
+ config = {
+ hostNames = mkDefault [ name ];
+ };
+ };
+in
+
+{
+ options = {
+
+ programs.ssh.knownHosts = mkOption {
+ default = {};
+ type = types.loaOf (types.submodule host);
+ description = ''
+ The set of system-wide known SSH hosts.
+ '';
+ example = literalExample ''
+ [
+ {
+ hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
+ publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub;
+ }
+ {
+ hostNames = [ "myhost2" ];
+ publicKeyFile = ./pubkeys/myhost2_ssh_host_dsa_key.pub;
+ }
+ ]
+ '';
+ };
+ };
+
+ config = {
+
+ assertions = 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";
+ });
+
+ environment.etc."ssh/ssh_known_hosts".text = (flip (concatMapStringsSep "\n") knownHosts
+ (h: assert h.hostNames != [];
+ concatStringsSep "," h.hostNames + " "
+ + (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
+ )) + "\n";
+
+ };
+}