greenhouse

kore

my public infrastructure monorepo

git clone [email protected]:kore.git

kore / nixos / features / kore.nix108 lines · 3001B · raw

1{ config, lib, kore, ... }:
2
3let
4  cfg = config.kore;
5  hostname = config.networking.hostName;
6
7  identityOptions = { name, ... }:
8    let
9      dir = ../../keys/identities + "/${name}";
10      sshDir = dir + "/ssh";
11      gpgFile = dir + "/gpg.asc";
12
13      sshFiles = lib.optionals (builtins.pathExists sshDir)
14        (lib.filter (lib.hasSuffix ".pub") (lib.attrNames (builtins.readDir sshDir)));
15    in {
16      options = with lib; {
17        email = mkOption {
18          type = types.nullOr types.str;
19          default = null;
20        };
21        gpg = mkOption {
22          type = types.nullOr types.str;
23          default = null;
24        };
25        sshKeys = mkOption {
26          type = types.listOf types.str;
27          default = map (file: lib.fileContents (sshDir + "/${file}")) sshFiles;
28        };
29        gpgKey = mkOption {
30          type = types.nullOr types.path;
31          default = if builtins.pathExists gpgFile then gpgFile else null;
32        };
33      };
34    };
35
36  hostOptions = with lib; {
37    system = mkOption {
38      type = types.str;
39    };
40    stateVersion = mkOption {
41      type = types.str;
42    };
43    roles = mkOption {
44      type = types.listOf types.str;
45      default = [];
46    };
47    users = mkOption {
48      type = types.listOf types.str;
49      default = [];
50    };
51    ipv4 = mkOption {
52      type = types.nullOr types.str;
53      default = null;
54    };
55  };
56in {
57  options.kore = with lib; {
58    identities = mkOption {
59      type = types.attrsOf (types.submodule identityOptions);
60      default = {};
61    };
62    hosts = mkOption {
63      type = types.attrsOf (types.submodule [{ options = hostOptions; }]);
64      default = {};
65    };
66    currentHost = mkOption {
67      type = types.submodule [{ options = hostOptions; }];
68    };
69
70    impermanence.enable = mkOption {
71      type = types.bool;
72      default = true;
73    };
74  };
75
76  config = {
77    kore = {
78      identities = kore.identities or {};
79      hosts = kore.hosts;
80      currentHost = kore.hosts.${hostname};
81    };
82
83    assertions = map (user: {
84      assertion = cfg.identities ? ${user};
85      message = "kore: ${hostname} has user ${user}, but kore.json has no identity for it";
86    }) cfg.currentHost.users;
87
88    nixpkgs.hostPlatform = cfg.currentHost.system;
89    system.stateVersion = cfg.currentHost.stateVersion;
90
91    users.users = lib.listToAttrs (lib.imap0 (i: user: lib.nameValuePair user {
92      isNormalUser = true;
93      password = "tmp";
94      extraGroups = [ "wheel" ];
95
96      subUidRanges = [{ startUid = 100000 + i * 65536; count = 65536; }];
97      subGidRanges = [{ startGid = 100000 + i * 65536; count = 65536; }];
98
99      openssh.authorizedKeys.keys = cfg.identities.${user}.sshKeys or [];
100    }) cfg.currentHost.users);
101
102    # /etc/hosts so machines resolve each other by name.
103    networking.hosts = lib.mkMerge (lib.mapAttrsToList (name: host:
104      lib.optionalAttrs (host.ipv4 != null) {
105        "${host.ipv4}" = [ "${name}.${config.networking.domain}" name ];
106      }) cfg.hosts);
107  };
108}