{ den, lib, ... }: let hostConfig = { host }: { nixos = { config, ... }: { services.openssh = { enable = true; settings = { PermitRootLogin = "no"; PasswordAuthentication = false; AllowUsers = lib.attrNames host.users; }; }; users.users = lib.mapAttrs (_: user: { openssh.authorizedKeys.keys = user.authorizedSshKeys; }) host.users; assertions = lib.optionals host.requiresSshRecovery ( let missingUsers = lib.filter (userName: !(builtins.hasAttr userName host.users)) host.sshRecoveryUsers; usersWithoutKeys = lib.filter ( userName: (builtins.hasAttr userName host.users) && host.users.${userName}.authorizedSshKeys == [ ] ) host.sshRecoveryUsers; in [ { assertion = config.services.openssh.enable; message = "Hosts with requiresSshRecovery must enable OpenSSH."; } { assertion = config.services.openssh.settings.PasswordAuthentication == false; message = "Hosts with requiresSshRecovery must disable SSH password authentication."; } { assertion = let rootLogin = config.services.openssh.settings.PermitRootLogin; in rootLogin == false || rootLogin == "no"; message = "Hosts with requiresSshRecovery must disable SSH root login."; } { assertion = host.sshRecoveryUsers != [ ]; message = "Hosts with requiresSshRecovery must declare at least one sshRecoveryUser."; } { assertion = missingUsers == [ ]; message = "All sshRecoveryUsers must exist on the host. Missing: " + lib.concatStringsSep ", " missingUsers; } { assertion = usersWithoutKeys == [ ]; message = "All sshRecoveryUsers must have plain authorizedSshKeys. Missing keys for: " + lib.concatStringsSep ", " usersWithoutKeys; } { assertion = host.sopsHostSshKeyPath != null; message = "Hosts with requiresSshRecovery must set sopsHostSshKeyPath."; } { assertion = config.services.openssh.openFirewall || lib.elem 22 config.networking.firewall.allowedTCPPorts; message = "Hosts with requiresSshRecovery must expose SSH through the firewall."; } ] ); }; }; in { lux.services._.openssh = den.lib.parametric.exactly { includes = [ hostConfig ]; }; }