261 lines
8.7 KiB
Nix
261 lines
8.7 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
let
|
|
cfg = config.fudo.services.nexus;
|
|
|
|
hostname = config.instance.hostname;
|
|
|
|
domainName = config.fudo.hosts."${hostname}".domain;
|
|
domain = config.fudo.domains."${domainName}";
|
|
siteName = config.fudo.hosts."${hostname}".site;
|
|
site = config.fudo.sites."${siteName}";
|
|
|
|
hostNexusDomainList = host:
|
|
let
|
|
domainName = config.fudo.hosts."${host}".domain;
|
|
domain = config.fudo.domains."${domainName}";
|
|
siteName = config.fudo.hosts."${host}".site;
|
|
site = config.fudo.sites."${siteName}";
|
|
in unique (domain.nexus.domains ++ site.nexus.domains);
|
|
|
|
isEmpty = lst: lst == [ ];
|
|
|
|
localNexusDomains = getAttrs (hostNexusDomainList hostname)
|
|
(listKeys config.fudo.nexus.domains);
|
|
|
|
isServer = let
|
|
servers = concatMap (domainOpts: domainOpts.servers)
|
|
(attrValues config.fudo.nexus.domains);
|
|
in elem hostname servers;
|
|
|
|
isDnsServer = let
|
|
servers = concatMap (domainOpts: domainOpts.dns-servers)
|
|
(attrValues config.fudo.nexus.domains);
|
|
in elem hostname servers;
|
|
|
|
isDatabase = hostname == domain.postgresql-server;
|
|
|
|
enableClient = !isEmpty (hostNexusDomainList hostname);
|
|
|
|
enable = isServer || isDnsServer || isDatabase || enableClient;
|
|
|
|
servedDomains = filterAttrs (_: domainOpts:
|
|
(elem hostname domainOpts.servers)
|
|
|| (elem hostname domainOpts.dns-servers)) config.fudo.nexus.domains;
|
|
|
|
clientHosts = filter (hostname:
|
|
!isEmpty
|
|
(intersectLists (hostNexusDomainList hostname) (attrNames servedDomains)))
|
|
(attrNames config.fudo.hosts);
|
|
|
|
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
|
|
|
hostFqdn = hostname: "${hostname}.${domainName}";
|
|
|
|
databaseName = "nexus_dns";
|
|
serverUser = "nexus_server";
|
|
dnsServerUser = "nexus_dns";
|
|
|
|
concatMapAttrsToList = f: as: concatLists (mapAttrsToList f as);
|
|
|
|
genServerRecords = name: domain: servers:
|
|
imap0 (i: host: {
|
|
inherit host domain;
|
|
alias = "${name}${toString i}";
|
|
}) servers;
|
|
|
|
serverList = concatMapAttrsToList
|
|
(domain: domainOpts: genServerRecords "nexus-" domain domainOpts.servers)
|
|
config.fudo.nexus.domains;
|
|
|
|
dnsServerList = concatMapAttrsToList
|
|
(domain: domainOpts: genServerRecords "ns" domain domainOpts.dns-servers)
|
|
config.fudo.nexus.domains;
|
|
|
|
genSshfp = path:
|
|
pkgs.stdenv.mkDerivation {
|
|
name = "sshfp-${baseNameOf path}";
|
|
buildInputs = with pkgs; [ openssh ];
|
|
phases = [ "installPhase" ];
|
|
installPhase =
|
|
"ssh-keygen -r PLACEHOLDER -f ${path} | sed 's/PLACEHOLDER IN SSHFP //' > $out";
|
|
};
|
|
|
|
in {
|
|
options.fudo.services.nexus.dns-server = with types; {
|
|
listen-addresses = mkOption {
|
|
type = nullOr (listOf str);
|
|
description =
|
|
"Listen addresses. Defaults to 0.0.0.0 (i.e. all addresses).";
|
|
default = null;
|
|
};
|
|
};
|
|
|
|
config = mkIf enable {
|
|
|
|
nexus = {
|
|
database = {
|
|
database = databaseName;
|
|
host = pkgs.lib.getDomainPostgresqlServer domainName;
|
|
};
|
|
|
|
domains = mapAttrs (domain: domainOpts: {
|
|
admin = "admin@${domain}";
|
|
inherit (domainOpts) gssapi-realm;
|
|
trusted-networks = domainOpts.trusted-networks
|
|
++ config.instance.local-networks;
|
|
# aliases = let
|
|
# mkAlias = { host, alias, ... }:
|
|
# nameValuePair alias (pkgs.lib.getHostFqdn host);
|
|
# domainRecords = filter (record: record.domain == domain) serverList;
|
|
# in listToAttrs (map mkAlias domainRecords);
|
|
nameservers = let
|
|
domainNs = filter (record: record.domain == domain) dnsServerList;
|
|
mkNsRecord = { alias, host, ... }:
|
|
nameValuePair alias {
|
|
ipv4-address = pkgs.lib.getHostIpv4 host;
|
|
ipv6-address = pkgs.lib.getHostIpv6 host;
|
|
};
|
|
in listToAttrs (map mkNsRecord domainNs);
|
|
records = let
|
|
domainServers = filter (record: record.domain == domain) serverList;
|
|
mkHostRecords = { host, alias, ... }:
|
|
let
|
|
ipv4-address = pkgs.lib.getHostIpv4 host;
|
|
ipv6-address = pkgs.lib.getHostIpv6 host;
|
|
in (optional (ipv4-address != null) {
|
|
name = "${alias}.${domain}";
|
|
type = "A";
|
|
content = ipv4-address;
|
|
}) ++ (optional (ipv6-address != null) {
|
|
name = "${alias}.${domain}";
|
|
type = "AAAA";
|
|
content = ipv6-address;
|
|
});
|
|
in domainOpts.records ++ (concatMap mkHostRecords domainServers);
|
|
}) servedDomains;
|
|
|
|
client = {
|
|
enable = enableClient;
|
|
inherit hostname;
|
|
verbose = true;
|
|
domains = unique (domain.nexus.domains ++ site.nexus.domains);
|
|
hmac-key-file = hostSecrets.nexus-key.target-file;
|
|
servers = let localDomains = hostNexusDomainList hostname;
|
|
in map ({ domain, alias, ... }: "${alias}.${domain}")
|
|
(filter ({ domain, ... }: elem domain localDomains) serverList);
|
|
ssh-key-files = map (key: key.path) config.services.openssh.hostKeys;
|
|
};
|
|
|
|
server = {
|
|
enable = isServer;
|
|
verbose = true;
|
|
client-keys-file = hostSecrets.nexus-client-keys.target-file;
|
|
hostnames = let
|
|
hostServerRecords =
|
|
filter ({ host, ... }: host == hostname) serverList;
|
|
in map ({ domain, alias, ... }: "${alias}.${domain}") hostServerRecords;
|
|
database = {
|
|
user = serverUser;
|
|
password-file = hostSecrets.nexus-server-passwd.target-file;
|
|
};
|
|
};
|
|
|
|
dns-server = {
|
|
enable = isDnsServer;
|
|
enable-dnssec = true;
|
|
listen-addresses = mkIf (cfg.dns-server.listen-addresses != null)
|
|
cfg.dns-server.listen-addresses;
|
|
database = {
|
|
user = dnsServerUser;
|
|
password-file = hostSecrets.nexus-dns-server-passwd.target-file;
|
|
};
|
|
};
|
|
};
|
|
|
|
fudo = {
|
|
secrets.host-secrets."${hostname}" = {
|
|
nexus-client-keys = mkIf isServer {
|
|
source-file = let
|
|
clientKeyFiles =
|
|
filterAttrs (hostname: _: elem hostname clientHosts)
|
|
config.fudo.secrets.files.nexus-hmacs;
|
|
clientKeys =
|
|
mapAttrs (_: filename: readFile filename) clientKeyFiles;
|
|
in pkgs.writeText "nexus-client-keys.json"
|
|
(builtins.toJSON clientKeys);
|
|
target-file = "/run/nexus/client-keys.json";
|
|
};
|
|
|
|
nexus-key = mkIf enableClient {
|
|
source-file = config.fudo.secrets.files.nexus-hmacs."${hostname}";
|
|
target-file = "/run/nexus/client.key";
|
|
};
|
|
|
|
nexus-server-passwd = mkIf isServer {
|
|
source-file =
|
|
pkgs.lib.passwd.stablerandom-passwd-file "nexus-server-passwd"
|
|
"nexus-server-${config.instance.build-seed}";
|
|
target-file = "/run/nexus/server-db.passwd";
|
|
};
|
|
|
|
postgres-nexus-server-passwd = mkIf isDatabase {
|
|
source-file =
|
|
pkgs.lib.passwd.stablerandom-passwd-file "nexus-server-passwd"
|
|
"nexus-server-${config.instance.build-seed}";
|
|
target-file = "/run/nexus/server-db.passwd";
|
|
user = "postgres";
|
|
};
|
|
|
|
nexus-dns-server-passwd = mkIf isDnsServer {
|
|
source-file =
|
|
pkgs.lib.passwd.stablerandom-passwd-file "nexus-dns-server-passwd"
|
|
"nexus-dns-server-${config.instance.build-seed}";
|
|
target-file = "/run/nexus/dns-server-db.passwd";
|
|
};
|
|
|
|
postgres-nexus-dns-server-passwd = mkIf isDatabase {
|
|
source-file =
|
|
pkgs.lib.passwd.stablerandom-passwd-file "nexus-dns-server-passwd"
|
|
"nexus-dns-server-${config.instance.build-seed}";
|
|
target-file = "/run/nexus-db/nexus-dns.passwd";
|
|
user = "postgres";
|
|
};
|
|
};
|
|
|
|
postgresql = mkIf isDatabase {
|
|
required-services = [ "fudo-passwords.target" ];
|
|
|
|
databases."${databaseName}".users = config.instance.local-admins;
|
|
|
|
users = {
|
|
"${serverUser}" = {
|
|
password-file =
|
|
hostSecrets.postgres-nexus-server-passwd.target-file;
|
|
databases."${databaseName}" = {
|
|
access = "CONNECT";
|
|
entity-access = {
|
|
"ALL TABLES IN SCHEMA public" = "SELECT,INSERT,UPDATE,DELETE";
|
|
"ALL SEQUENCES IN SCHEMA public" = "SELECT,UPDATE";
|
|
};
|
|
};
|
|
};
|
|
|
|
"${dnsServerUser}" = {
|
|
password-file =
|
|
hostSecrets.postgres-nexus-dns-server-passwd.target-file;
|
|
databases."${databaseName}" = {
|
|
access = "CONNECT";
|
|
entity-access = {
|
|
"ALL TABLES IN SCHEMA public" = "SELECT,INSERT,UPDATE,DELETE";
|
|
"ALL SEQUENCES IN SCHEMA public" = "SELECT,UPDATE";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|