diff --git a/hosts/common/ssh.nix b/hosts/common/ssh.nix index c76b6345d..874a6d218 100644 --- a/hosts/common/ssh.nix +++ b/hosts/common/ssh.nix @@ -1,10 +1,22 @@ { config, lib, ... }: { + # persist the host key environment.etc."ssh/host_keys".source = "/nix/persist/etc/ssh/host_keys"; + # let openssh find our host keys services.openssh.hostKeys = [ { type = "rsa"; bits = 4096; path = "/etc/ssh/host_keys/ssh_host_rsa_key"; } { type = "ed25519"; path = "/etc/ssh/host_keys/ssh_host_ed25519_key"; } ]; + sane.ssh.pubkeys = { + "colin@lappy" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu"; + "root@lappy" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc"; + "root@desko" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk"; + "colin@desko" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX"; + "root@servo" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8"; + "colin@servo" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX"; + "root@moby" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw"; + "colin@moby" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU"; + }; } diff --git a/hosts/common/users.nix b/hosts/common/users.nix index 1cfb81687..234dcf6d5 100644 --- a/hosts/common/users.nix +++ b/hosts/common/users.nix @@ -52,7 +52,11 @@ in passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path; shell = pkgs.zsh; - openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users; + openssh.authorizedKeys.keys = + let + user-keys = filter (k: k.user == "colin") (attrValues config.sane.ssh.pubkeys); + in + map (k: k.asUserKey) user-keys; # mount encrypted stuff at login # some other nix pam users: diff --git a/modules/default.nix b/modules/default.nix index fe0ba6e2f..39b75f9f5 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -12,6 +12,7 @@ ./persist ./services ./sops.nix + ./ssh.nix ]; _module.args = { diff --git a/modules/home-manager/ssh.nix b/modules/home-manager/ssh.nix index cdf2fdb3c..eb90890e6 100644 --- a/modules/home-manager/ssh.nix +++ b/modules/home-manager/ssh.nix @@ -1,19 +1,22 @@ { config, lib, pkgs, sane-lib, ... }: +with lib; let host = config.networking.hostName; - user_pubkey = (import ../pubkeys.nix).users."${host}"; - known_hosts_text = builtins.concatStringsSep + user-pubkey = config.sane.ssh.pubkeys."colin@${host}".asUserKey; + host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys); + known-hosts-text = concatStringsSep "\n" - (builtins.attrValues (import ../pubkeys.nix).hosts); + (map (k: k.asHostKey) host-keys) + ; in lib.mkIf config.sane.home-manager.enable { # ssh key is stored in private storage sane.persist.home.private = [ ".ssh/id_ed25519" ]; - sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user_pubkey; + sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user-pubkey; home-manager.users.colin = { programs.ssh.enable = true; # this optionally accepts multiple known_hosts paths, separated by space. - programs.ssh.userKnownHostsFile = builtins.toString (pkgs.writeText "known_hosts" known_hosts_text); + programs.ssh.userKnownHostsFile = toString (pkgs.writeText "known_hosts" known-hosts-text); }; } diff --git a/modules/pubkeys.nix b/modules/pubkeys.nix deleted file mode 100644 index 59f3decfb..000000000 --- a/modules/pubkeys.nix +++ /dev/null @@ -1,34 +0,0 @@ -# create ssh key by running: -# - `ssh-keygen -t ed25519` -let - withHost = host: key: "${host} ${key}"; - withUser = user: key: "${key} ${user}"; - - keys = rec { - lappy = { - host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc"; - users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu"; - }; - desko = { - host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk"; - users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX"; - }; - servo = { - host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8"; - users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX"; - }; - moby = { - host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw"; - users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU"; - }; - - "uninsane.org" = servo; - "git.uninsane.org" = servo; - }; -in { - # map hostname -> something suitable for known_keys - hosts = builtins.mapAttrs (host: keys: withHost host keys.host) keys; - # map hostname -> something suitable for authorized_keys to allow access to colin@ - users = builtins.mapAttrs (host: keys: withUser "colin@${host}" keys.users.colin) keys; -} - diff --git a/modules/ssh.nix b/modules/ssh.nix new file mode 100644 index 000000000..7cbcc8507 --- /dev/null +++ b/modules/ssh.nix @@ -0,0 +1,66 @@ +{ lib, ... }: + +with lib; +let + key = types.submodule ({ name, config, ...}: { + options = { + typedPubkey = mkOption { + type = types.str; + description = '' + the pubkey with type attached. + e.g. "ssh-ed25519 " + ''; + }; + # type = mkOption { + # type = types.str; + # description = '' + # the type of the key, e.g. "id_ed25519" + # ''; + # }; + host = mkOption { + type = types.str; + description = '' + the hostname of a key + ''; + }; + user = mkOption { + type = types.str; + description = '' + the username of a key + ''; + }; + asUserKey = mkOption { + type = types.str; + description = '' + append the "user@host" value to the pubkey to make it usable for ~/.ssh/id_.pub or authorized_keys + ''; + }; + asHostKey = mkOption { + type = types.str; + description = '' + prepend the "host" value to the pubkey to make it usable for ~/.ssh/known_hosts + ''; + }; + }; + config = rec { + user = head (lib.splitString "@" name); + host = last (lib.splitString "@" name); + asUserKey = "${config.typedPubkey} ${name}"; + asHostKey = "${host} ${config.typedPubkey}"; + }; + }); + coercedToKey = types.coercedTo types.str (typedPubkey: { + inherit typedPubkey; + }) key; +in +{ + options = { + sane.ssh.pubkeys = mkOption { + type = types.attrsOf coercedToKey; + default = []; + description = '' + mapping from "user@host" to pubkey. + ''; + }; + }; +}