{ pkgs, config, osConfig, lib, ... }: { options.programs.openssh = { authorizedKeys = lib.mkOption { type = lib.types.listOf lib.types.str; default = []; }; hostKeys = lib.mkOption { type = lib.types.listOf lib.types.attrs; default = []; example = [ { type = "rsa"; bits = 4096; path = "${config.home.username}_${osConfig.networking.hostName}_rsa"; rounds = 100; openSSHFormat = true; } { type = "ed25519"; path = "${config.home.username}_${osConfig.networking.hostName}_ed25519"; rounds = 100; comment = "key comment"; } ]; description = '' NixOS can automatically generate SSH host keys. This option specifies the path, type and size of each key. See {manpage}`ssh-keygen(1)` for supported types and sizes. Paths are relative to home directory ''; }; }; config = lib.mkMerge [ ( lib.mkIf ((builtins.length config.programs.openssh.hostKeys) != 0) { services.ssh-agent.enable = true; programs.ssh = { enable = true; compression = true; addKeysToAgent = "confirm"; extraConfig = lib.strings.concatLines ( builtins.map (hostKey: "IdentityFile ~/.ssh/${hostKey.path}") config.programs.openssh.hostKeys ); }; systemd.user.services = builtins.listToAttrs ( builtins.map (hostKey: lib.attrsets.nameValuePair "ssh-gen-keys-${hostKey.path}" { Install = { WantedBy = ["default.target"]; }; Service = let path = "${config.home.homeDirectory}/.ssh/${hostKey.path}"; in { Restart = "always"; Type = "simple"; ExecStart = "${ pkgs.writeShellScript "ssh-gen-keys" '' if ! [ -s "${path}" ]; then if ! [ -h "${path}" ]; then rm -f "${path}" fi mkdir -p "$(dirname '${path}')" chmod 0755 "$(dirname '${path}')" ${pkgs.openssh}/bin/ssh-keygen \ -t "${hostKey.type}" \ ${lib.optionalString (hostKey ? bits) "-b ${toString hostKey.bits}"} \ ${lib.optionalString (hostKey ? rounds) "-a ${toString hostKey.rounds}"} \ ${lib.optionalString (hostKey ? comment) "-C '${hostKey.comment}'"} \ ${lib.optionalString (hostKey ? openSSHFormat && hostKey.openSSHFormat) "-o"} \ -f "${path}" \ -N "" chown ${config.home.username} ${path}* chgrp ${config.home.username} ${path}* fi '' }"; }; }) config.programs.openssh.hostKeys ); } ) (lib.mkIf osConfig.host.impermanence.enable { home.persistence."/persist${config.home.homeDirectory}" = { files = lib.lists.flatten ( builtins.map (hostKey: [".ssh/${hostKey.path}" ".ssh/${hostKey.path}.pub"]) config.programs.openssh.hostKeys ); }; }) ]; }