main
 1{
 2  den,
 3  lib,
 4  ...
 5}: let
 6  hostKeys = [
 7    {
 8      path = "/etc/ssh/ssh_host_ed25519_key";
 9      type = "ed25519";
10    }
11    {
12      path = "/etc/ssh/ssh_host_rsa_key";
13      type = "rsa";
14      bit = 4096;
15    }
16  ];
17
18  hostKeyFiles = builtins.concatMap (key: [key.path] ++ ["${key.path}.pub"]) hostKeys;
19in {
20  den.aspects.core.includes = [den.aspects.core.openssh];
21
22  den.aspects.core.openssh = {
23    settings.host = {
24      server = {
25        enable = lib.mkEnableOption "Whether to start OpenSSH server";
26        port = lib.mkOption {
27          type = lib.types.port;
28          default = 22;
29        };
30      };
31      authorizedKeys = lib.mkOption {
32        type = lib.types.listOf lib.types.str;
33        default = [];
34        description = "SSH authorized keys for root on this host.";
35      };
36    };
37
38    persist = {
39      files =
40        map (file: {
41          inherit file;
42          mode = "06${
43            if lib.strings.hasSuffix ".pub" file
44            then "44"
45            else "00"
46          }";
47        })
48        hostKeyFiles;
49    };
50    persistHome = {
51      directories = [
52        {
53          directory = ".ssh";
54          mode = "0700";
55        }
56      ];
57    };
58
59    nixos = {host, ...}: {
60      services.openssh = {
61        enable = host.settings.core.openssh.server.enable;
62        # Serve on 22 port for Tailscale
63        ports = lib.unique [22 host.settings.core.openssh.server.port];
64        generateHostKeys = true;
65        inherit hostKeys;
66        settings = {
67          PermitRootLogin = "prohibit-password";
68          PasswordAuthentication = false;
69        };
70        # Mannualy open filewall
71        openFirewall = false;
72      };
73
74      users.users.root.openssh.authorizedKeys.keys =
75        host.settings.core.openssh.authorizedKeys;
76
77      networking.firewall.allowedTCPPorts = [
78        host.settings.core.openssh.server.port
79      ];
80
81      environment.enableAllTerminfo = host.settings.core.openssh.server.enable;
82    };
83
84    provides.to-users = {
85      user = {user, ...}: {
86        openssh.authorizedKeys.keys = user.identity.sshKeys;
87      };
88    };
89  };
90}