2023-12-04 20:23:31 +02:00
|
|
|
{ cluster, config, depot, lib, pkgs, ... }:
|
2022-08-07 22:06:17 +03:00
|
|
|
|
2023-12-04 20:23:31 +02:00
|
|
|
let
|
|
|
|
authoritativeServers = map
|
|
|
|
(node: cluster.config.hostLinks.${node}.dnsAuthoritative.tuple)
|
|
|
|
cluster.config.services.dns.nodes.authoritative;
|
2022-08-07 22:06:17 +03:00
|
|
|
|
2023-12-04 20:23:31 +02:00
|
|
|
execScript = pkgs.writeShellScript "acme-dns-exec" ''
|
|
|
|
action="$1"
|
|
|
|
subdomain="''${2%.${depot.lib.meta.domain}.}"
|
|
|
|
key="$3"
|
|
|
|
umask 77
|
|
|
|
source "$EXEC_ENV_FILE"
|
|
|
|
headersFile="$(mktemp)"
|
|
|
|
echo "X-Direct-Key: $ACME_DNS_DIRECT_STATIC_KEY" > "$headersFile"
|
|
|
|
case "$action" in
|
|
|
|
present)
|
|
|
|
for i in {1..5}; do
|
|
|
|
${pkgs.curl}/bin/curl -X POST -s -f -H "@$headersFile" \
|
|
|
|
"${cluster.config.links.acmeDnsApi.url}/update" \
|
|
|
|
--data '{"subdomain":"'"$subdomain"'","txt":"'"$key"'"}' && break
|
|
|
|
sleep 5
|
|
|
|
done
|
|
|
|
;;
|
|
|
|
esac
|
2022-08-07 22:06:17 +03:00
|
|
|
'';
|
2023-12-04 20:23:31 +02:00
|
|
|
in
|
|
|
|
|
|
|
|
{
|
|
|
|
age.secrets.acmeDnsApiKey = {
|
|
|
|
file = ../dns/acme-dns-direct-key.age;
|
|
|
|
owner = "acme";
|
|
|
|
};
|
|
|
|
|
2024-08-10 14:35:21 +03:00
|
|
|
security.acme.acceptTerms = true;
|
|
|
|
security.acme.maxConcurrentRenewals = 0;
|
2023-12-04 20:23:31 +02:00
|
|
|
security.acme.defaults = {
|
2024-08-10 14:35:21 +03:00
|
|
|
email = depot.lib.meta.adminEmail;
|
2023-12-04 20:23:31 +02:00
|
|
|
extraLegoFlags = lib.flatten [
|
|
|
|
(map (x: [ "--dns.resolvers" x ]) authoritativeServers)
|
|
|
|
"--dns-timeout" "30"
|
|
|
|
];
|
|
|
|
credentialsFile = pkgs.writeText "acme-exec-config" ''
|
|
|
|
EXEC_PATH=${execScript}
|
|
|
|
EXEC_ENV_FILE=${config.age.secrets.acmeDnsApiKey.path}
|
|
|
|
'';
|
|
|
|
};
|
2024-08-10 14:35:21 +03:00
|
|
|
|
|
|
|
systemd.services = lib.mapAttrs' (name: value: {
|
|
|
|
name = "acme-${name}";
|
|
|
|
value = {
|
|
|
|
distributed.enable = value.dnsProvider != null;
|
|
|
|
preStart = let
|
|
|
|
serverList = lib.pipe authoritativeServers [
|
|
|
|
(map (x: "@${x}"))
|
|
|
|
(map (lib.replaceStrings [":53"] [""]))
|
|
|
|
lib.escapeShellArgs
|
|
|
|
];
|
|
|
|
domainList = lib.pipe ([ value.domain ] ++ value.extraDomainNames) [
|
|
|
|
(map (x: "${x}."))
|
|
|
|
(map (lib.replaceStrings ["*"] ["x"]))
|
|
|
|
lib.unique
|
|
|
|
lib.escapeShellArgs
|
|
|
|
];
|
|
|
|
in ''
|
|
|
|
echo Testing availability of authoritative DNS servers
|
|
|
|
for i in {1..60}; do
|
|
|
|
${pkgs.dig}/bin/dig +short ${serverList} ${domainList} >/dev/null && break
|
|
|
|
echo Retry [$i/60]
|
|
|
|
sleep 10
|
|
|
|
done
|
|
|
|
echo Available
|
|
|
|
'';
|
|
|
|
serviceConfig = {
|
|
|
|
Restart = "on-failure";
|
|
|
|
RestartMaxDelaySec = 30;
|
|
|
|
RestartStesp = 5;
|
|
|
|
RestartMode = "direct";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}) config.security.acme.certs;
|
2022-08-07 22:06:17 +03:00
|
|
|
}
|