nixpkgs/nixos/modules/services/security/certmgr.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

228 lines
6.3 KiB
Nix
Raw Permalink Normal View History

2018-08-06 14:28:52 +02:00
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.certmgr;
specs = lib.mapAttrsToList (n: v: rec {
2018-08-06 14:28:52 +02:00
name = n + ".json";
path = if lib.isAttrs v then pkgs.writeText name (builtins.toJSON v) else v;
2018-08-06 14:28:52 +02:00
}) cfg.specs;
allSpecs = pkgs.linkFarm "certmgr.d" specs;
certmgrYaml = pkgs.writeText "certmgr.yaml" (
builtins.toJSON {
dir = allSpecs;
default_remote = cfg.defaultRemote;
svcmgr = cfg.svcManager;
before = cfg.validMin;
interval = cfg.renewInterval;
inherit (cfg) metricsPort metricsAddress;
}
);
2018-08-06 14:28:52 +02:00
specPaths = map dirOf (
lib.concatMap (
2018-08-06 14:28:52 +02:00
spec:
if lib.isAttrs spec then
lib.collect lib.isString (lib.filterAttrsRecursive (n: v: lib.isAttrs v || n == "path") spec)
2018-08-06 14:28:52 +02:00
else
[ spec ]
) (lib.attrValues cfg.specs)
2018-08-06 14:28:52 +02:00
);
preStart = ''
${lib.concatStringsSep " \\\n" ([ "mkdir -p" ] ++ map lib.escapeShellArg specPaths)}
2019-01-24 12:11:15 +01:00
${cfg.package}/bin/certmgr -f ${certmgrYaml} check
2018-08-06 14:28:52 +02:00
'';
in
{
options.services.certmgr = {
enable = lib.mkEnableOption "certmgr";
2018-08-06 14:28:52 +02:00
package = lib.mkPackageOption pkgs "certmgr" { };
2019-01-24 12:11:15 +01:00
defaultRemote = lib.mkOption {
type = lib.types.str;
2018-08-06 14:28:52 +02:00
default = "127.0.0.1:8888";
description = "The default CA host:port to use.";
};
validMin = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = "72h";
type = lib.types.str;
2018-08-06 14:28:52 +02:00
description = "The interval before a certificate expires to start attempting to renew it.";
};
renewInterval = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = "30m";
type = lib.types.str;
2018-08-06 14:28:52 +02:00
description = "How often to check certificate expirations and how often to update the cert_next_expires metric.";
};
metricsAddress = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = "127.0.0.1";
type = lib.types.str;
2018-08-06 14:28:52 +02:00
description = "The address for the Prometheus HTTP endpoint.";
};
metricsPort = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = 9488;
type = lib.types.ints.u16;
2018-08-06 14:28:52 +02:00
description = "The port for the Prometheus HTTP endpoint.";
};
specs = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = { };
example = lib.literalExpression ''
2018-08-06 14:28:52 +02:00
{
exampleCert =
let
domain = "example.com";
secret = name: "/var/lib/secrets/''${name}.pem";
in {
service = "nginx";
action = "reload";
authority = {
file.path = secret "ca";
};
certificate = {
path = secret domain;
};
2018-08-06 14:28:52 +02:00
private_key = {
owner = "root";
group = "root";
mode = "0600";
path = secret "''${domain}-key";
};
2018-08-06 14:28:52 +02:00
request = {
CN = domain;
hosts = [ "mail.''${domain}" "www.''${domain}" ];
key = {
2018-08-06 14:28:52 +02:00
algo = "rsa";
size = 2048;
};
2018-08-06 14:28:52 +02:00
names = {
O = "Example Organization";
C = "USA";
};
2018-08-06 14:28:52 +02:00
};
};
otherCert = "/var/certmgr/specs/other-cert.json";
}
'';
type =
with lib.types;
attrsOf (
either path (submodule {
2018-08-06 14:28:52 +02:00
options = {
service = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = nullOr str;
default = null;
2024-12-23 21:58:07 +01:00
description = "The service on which to perform \\<action\\> after fetching.";
2018-08-06 14:28:52 +02:00
};
action = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = addCheck str (
x:
cfg.svcManager == "command"
2025-01-01 11:19:35 -08:00
|| lib.elem x [
2018-08-06 14:28:52 +02:00
"restart"
"reload"
"nop"
]
2018-08-06 14:28:52 +02:00
);
default = "nop";
description = "The action to take after fetching.";
2018-08-06 14:28:52 +02:00
};
2018-08-06 14:28:52 +02:00
# These ought all to be specified according to certmgr spec def.
authority = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = attrs;
description = "certmgr spec authority object.";
2018-08-06 14:28:52 +02:00
};
certificate = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = nullOr attrs;
description = "certmgr spec certificate object.";
2018-08-06 14:28:52 +02:00
};
private_key = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = nullOr attrs;
description = "certmgr spec private_key object.";
2018-08-06 14:28:52 +02:00
};
request = lib.mkOption {
2018-08-06 14:28:52 +02:00
type = nullOr attrs;
description = "certmgr spec request object.";
2018-08-06 14:28:52 +02:00
};
};
})
);
2018-08-06 14:28:52 +02:00
description = ''
Certificate specs as described by:
<https://github.com/cloudflare/certmgr#certificate-specs>
These will be added to the Nix store, so they will be world readable.
'';
};
svcManager = lib.mkOption {
2018-08-06 14:28:52 +02:00
default = "systemd";
type = lib.types.enum [
2018-08-06 14:28:52 +02:00
"circus"
"command"
"dummy"
"openrc"
"systemd"
"sysv"
];
description = ''
This specifies the service manager to use for restarting or reloading services.
See: <https://github.com/cloudflare/certmgr#certmgryaml>.
For how to use the "command" service manager in particular,
see: <https://github.com/cloudflare/certmgr#command-svcmgr-and-how-to-use-it>.
'';
};
};
config = lib.mkIf cfg.enable {
2018-08-06 14:28:52 +02:00
assertions = [
{
assertion = cfg.specs != { };
message = "Certmgr specs cannot be empty.";
}
{
assertion =
!lib.any (lib.hasAttrByPath [
2018-08-06 14:28:52 +02:00
"authority"
"auth_key"
]) (lib.attrValues cfg.specs);
2018-08-06 14:28:52 +02:00
message = ''
Inline services.certmgr.specs are added to the Nix store rendering them world readable.
Specify paths as specs, if you want to use include auth_key - or use the auth_key_file option."
'';
}
];
systemd.services.certmgr = {
description = "certmgr";
path = lib.mkIf (cfg.svcManager == "command") [ pkgs.bash ];
wants = [ "network-online.target" ];
2018-08-06 14:28:52 +02:00
after = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
inherit preStart;
serviceConfig = {
Restart = "always";
RestartSec = "10s";
2019-01-24 12:11:15 +01:00
ExecStart = "${cfg.package}/bin/certmgr -f ${certmgrYaml}";
2018-08-06 14:28:52 +02:00
};
};
};
}