2022-03-17 23:31:55 +00:00
|
|
|
# SPDX-FileCopyrightText: 2022 Luke Granger-Brown <depot@lukegb.com>
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
{ pkgs, config, depot, lib, ... }:
|
|
|
|
let
|
|
|
|
inherit (lib) mkOption types mkBefore optionalAttrs mkDefault mkIf mapAttrsToList mkAfter;
|
|
|
|
|
|
|
|
acmeCertificates = builtins.attrValues config.my.vault.acmeCertificates;
|
|
|
|
|
|
|
|
# Work out where we're being asked to write things, and which groups, so we can correctly get permissions.
|
|
|
|
fullchainPath = c: pathFor c "fullchain.pem";
|
|
|
|
chainPath = c: pathFor c "chain.pem";
|
|
|
|
keyPath = c: pathFor c "privkey.pem";
|
|
|
|
pathFor = c: suffix: "/var/lib/acme/${c.name}/${suffix}";
|
|
|
|
|
|
|
|
isNginx = c: builtins.length c.nginxVirtualHosts > 0;
|
|
|
|
defaultGroup = c: if isNull c.group then if isNginx c then "nginx" else "acme" else c.group;
|
|
|
|
groupOrDefault = p: c: if isNull p then defaultGroup c else p;
|
|
|
|
|
|
|
|
allRestartableUnits = builtins.concatMap (c: c.reloadOrRestartUnits) acmeCertificates;
|
|
|
|
allGroups = lib.unique (map (c: c.group) acmeCertificates);
|
|
|
|
in
|
|
|
|
{
|
|
|
|
imports = [
|
|
|
|
./secretsmgr.nix
|
|
|
|
];
|
|
|
|
|
|
|
|
options.my.vault.acmeCertificates = mkOption {
|
|
|
|
default = {};
|
|
|
|
type = with types; attrsOf (submodule ({ name, config, ... }: {
|
|
|
|
options = let
|
|
|
|
isNginx = builtins.length config.nginxVirtualHosts > 0;
|
|
|
|
in {
|
|
|
|
name = mkOption {
|
|
|
|
type = str;
|
|
|
|
default = name;
|
|
|
|
description = "Path to put the certificate.";
|
|
|
|
};
|
|
|
|
|
|
|
|
nginxVirtualHosts = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [];
|
|
|
|
description = "List of nginx virtual hosts to apply SSL to.";
|
|
|
|
};
|
2024-10-20 16:21:54 +00:00
|
|
|
caddyVirtualHosts = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = [];
|
|
|
|
description = "List of caddy virtual hosts to apply SSL to.";
|
|
|
|
};
|
2022-03-17 23:31:55 +00:00
|
|
|
group = mkOption {
|
|
|
|
type = str;
|
|
|
|
default = if isNginx then "nginx" else "acme";
|
|
|
|
description = "Owner group to set for the ${what}. If null, taken from parent.";
|
|
|
|
};
|
|
|
|
|
|
|
|
role = mkOption {
|
|
|
|
type = str;
|
2022-08-10 00:51:46 +00:00
|
|
|
default = "google-cloudflare";
|
2022-03-17 23:31:55 +00:00
|
|
|
description = "Which role to use for certificate issuance.";
|
|
|
|
};
|
|
|
|
|
|
|
|
hostnames = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
description = "List of hostnames to issue certificate for.";
|
|
|
|
};
|
|
|
|
|
|
|
|
reloadOrRestartUnits = mkOption {
|
|
|
|
type = listOf str;
|
|
|
|
default = lib.optional isNginx "nginx.service";
|
|
|
|
description = "List of systemd units to reload/restart after obtaining a new certificate.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf config.my.vault.secretsmgr.acmeCertificates.enable {
|
|
|
|
services.nginx = optionalAttrs config.my.vault.enable {
|
2024-10-20 16:21:54 +00:00
|
|
|
virtualHosts = builtins.listToAttrs (builtins.concatMap (certData:
|
|
|
|
map (hostName: lib.nameValuePair hostName {
|
|
|
|
sslCertificate = mkDefault (fullchainPath certData);
|
|
|
|
sslCertificateKey = mkDefault (keyPath certData);
|
|
|
|
sslTrustedCertificate = mkDefault (chainPath certData);
|
|
|
|
}) certData.nginxVirtualHosts) acmeCertificates);
|
|
|
|
};
|
|
|
|
services.caddy = optionalAttrs config.my.vault.enable {
|
|
|
|
virtualHosts = builtins.listToAttrs (builtins.concatMap (certData:
|
|
|
|
map (hostName: lib.nameValuePair hostName {
|
|
|
|
extraConfig = lib.mkBefore ''
|
|
|
|
tls ${fullchainPath certData} ${keyPath certData}
|
|
|
|
'';
|
|
|
|
}) certData.caddyVirtualHosts) acmeCertificates);
|
2022-03-17 23:31:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
my.vault.secretsmgr.groups = mkAfter allGroups;
|
|
|
|
my.vault.secretsmgr.restartableUnits = mkAfter allRestartableUnits;
|
|
|
|
my.vault.secretsmgr.acmeCertificates.config = mapAttrsToList (_: c: {
|
|
|
|
inherit (c) group hostnames role;
|
|
|
|
output_name = c.name;
|
|
|
|
units_to_reload_or_restart = c.reloadOrRestartUnits;
|
|
|
|
}) config.my.vault.acmeCertificates;
|
2024-10-20 13:37:47 +00:00
|
|
|
|
|
|
|
users.groups = lib.listToAttrs (lib.map (groupName: lib.nameValuePair groupName {}) allGroups);
|
2022-03-17 23:31:55 +00:00
|
|
|
};
|
|
|
|
}
|