infrastructure/nixos/acme.nix

76 lines
1.9 KiB
Nix

{
config,
lib,
...
}: let
inherit (lib.modules) mkMerge mkDefault;
inherit (lib.strings) removePrefix splitString concatStringsSep;
inherit (lib.lists) head optional;
cfg = config.security.acme;
mkHash = with builtins; val: substring 0 20 (hashString "sha256" val);
mkAccountHash = {
server ? null,
keyType,
email,
}:
mkHash "${toString server} ${keyType} ${email}";
mkHost = server: head (splitString "/" (removePrefix "https://" server));
mkAccountDir = {
server ? null,
email,
keyType,
}:
concatStringsSep "/" ([
accountDirRoot
(mkAccountHash {inherit server email keyType;})
]
++ optional (server != null) (
mkHost server
)
++ [
cfg.defaults.email
]);
accountDirRoot = "/var/lib/acme/.lego/accounts";
addr = concatStringsSep "@" ["gensokyo" "arcn.mx"];
in {
security.acme = {
acceptTerms = true;
defaults = {
email = mkDefault addr;
server = mkDefault "https://acme-v02.api.letsencrypt.org/directory";
keyType = mkDefault "ec384";
dnsProvider = mkDefault "cloudflare";
credentialFiles = {
CLOUDFLARE_EMAIL_FILE = config.sops.secrets.acme_cloudflare_email.path;
CLOUDFLARE_DNS_API_TOKEN_FILE = config.sops.secrets.acme_cloudflare_token.path;
};
};
};
sops.secrets = let
accountDir = mkAccountDir {inherit (cfg.defaults) server email keyType;};
acmeSecret = {
sopsFile = mkDefault ./secrets/acme.yaml;
owner = "acme";
group = "nginx";
};
in {
acme_account_key = mkMerge [
acmeSecret
{
path = accountDir + "/keys/${cfg.defaults.email}.key";
}
];
acme_cloudflare_email = acmeSecret;
acme_cloudflare_token = acmeSecret;
};
systemd.services = let
after = [ "systemd-tmpfiles-resetup.service" ];
in {
acme-fixperms = {
inherit after;
};
acme-lockfiles = {
inherit after;
};
};
}