forked from mirrors/nixpkgs
Merge pull request #31833 from pngwjpgh/feat/acme/delay
nixos/acme: Allow for time window between cert issue and activation
This commit is contained in:
commit
1b0a7bfe38
|
@ -58,9 +58,11 @@ let
|
||||||
default = "";
|
default = "";
|
||||||
example = "systemctl reload nginx.service";
|
example = "systemctl reload nginx.service";
|
||||||
description = ''
|
description = ''
|
||||||
Commands to run after certificates are re-issued. Typically
|
Commands to run after new certificates go live. Typically
|
||||||
the web server and other servers using certificates need to
|
the web server and other servers using certificates need to
|
||||||
be reloaded.
|
be reloaded.
|
||||||
|
|
||||||
|
Executed in the same directory with the new certificate.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,6 +80,27 @@ let
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
activationDelay = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Systemd time span expression to delay copying new certificates to main
|
||||||
|
state directory. See <citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||||
|
<manvolnum>7</manvolnum></citerefentry>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
preDelay = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = ''
|
||||||
|
Commands to run after certificates are re-issued but before they are
|
||||||
|
activated. Typically the new certificate is published to DNS.
|
||||||
|
|
||||||
|
Executed in the same directory with the new certificate.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
extraDomains = mkOption {
|
extraDomains = mkOption {
|
||||||
type = types.attrsOf (types.nullOr types.str);
|
type = types.attrsOf (types.nullOr types.str);
|
||||||
default = {};
|
default = {};
|
||||||
|
@ -186,14 +209,15 @@ in
|
||||||
servicesLists = mapAttrsToList certToServices cfg.certs;
|
servicesLists = mapAttrsToList certToServices cfg.certs;
|
||||||
certToServices = cert: data:
|
certToServices = cert: data:
|
||||||
let
|
let
|
||||||
cpath = "${cfg.directory}/${cert}";
|
domain = if data.domain != null then data.domain else cert;
|
||||||
|
cpath = lpath + optionalString (data.activationDelay != null) ".staging";
|
||||||
|
lpath = "${cfg.directory}/${cert}";
|
||||||
rights = if data.allowKeysForGroup then "750" else "700";
|
rights = if data.allowKeysForGroup then "750" else "700";
|
||||||
cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
|
cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
|
||||||
++ optionals (data.email != null) [ "--email" data.email ]
|
++ optionals (data.email != null) [ "--email" data.email ]
|
||||||
++ concatMap (p: [ "-f" p ]) data.plugins
|
++ concatMap (p: [ "-f" p ]) data.plugins
|
||||||
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
|
++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
|
||||||
++ (if cfg.production then []
|
++ optionals (!cfg.production) ["--server" "https://acme-staging.api.letsencrypt.org/directory"];
|
||||||
else ["--server" "https://acme-staging.api.letsencrypt.org/directory"]);
|
|
||||||
acmeService = {
|
acmeService = {
|
||||||
description = "Renew ACME Certificate for ${cert}";
|
description = "Renew ACME Certificate for ${cert}";
|
||||||
after = [ "network.target" "network-online.target" ];
|
after = [ "network.target" "network-online.target" ];
|
||||||
|
@ -206,7 +230,7 @@ in
|
||||||
Group = data.group;
|
Group = data.group;
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
};
|
};
|
||||||
path = [ pkgs.simp_le ];
|
path = with pkgs; [ simp_le systemd ];
|
||||||
preStart = ''
|
preStart = ''
|
||||||
mkdir -p '${cfg.directory}'
|
mkdir -p '${cfg.directory}'
|
||||||
chown 'root:root' '${cfg.directory}'
|
chown 'root:root' '${cfg.directory}'
|
||||||
|
@ -229,15 +253,36 @@ in
|
||||||
exit "$EXITCODE"
|
exit "$EXITCODE"
|
||||||
'';
|
'';
|
||||||
postStop = ''
|
postStop = ''
|
||||||
|
cd '${cpath}'
|
||||||
|
|
||||||
if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then
|
if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then
|
||||||
echo "Executing postRun hook..."
|
${if data.activationDelay != null then ''
|
||||||
${data.postRun}
|
|
||||||
|
${data.preDelay}
|
||||||
|
|
||||||
|
if [ -d '${lpath}' ]; then
|
||||||
|
systemd-run --no-block --on-active='${data.activationDelay}' --unit acme-setlive-${cert}.service
|
||||||
|
else
|
||||||
|
systemctl --wait start acme-setlive-${cert}.service
|
||||||
|
fi
|
||||||
|
'' else data.postRun}
|
||||||
fi
|
fi
|
||||||
'';
|
'';
|
||||||
|
|
||||||
before = [ "acme-certificates.target" ];
|
before = [ "acme-certificates.target" ];
|
||||||
wantedBy = [ "acme-certificates.target" ];
|
wantedBy = [ "acme-certificates.target" ];
|
||||||
};
|
};
|
||||||
|
delayService = {
|
||||||
|
description = "Set certificate for ${cert} live";
|
||||||
|
path = with pkgs; [ rsync ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
rsync -a --delete-after '${cpath}/' '${lpath}'
|
||||||
|
'';
|
||||||
|
postStop = data.postRun;
|
||||||
|
};
|
||||||
selfsignedService = {
|
selfsignedService = {
|
||||||
description = "Create preliminary self-signed certificate for ${cert}";
|
description = "Create preliminary self-signed certificate for ${cert}";
|
||||||
path = [ pkgs.openssl ];
|
path = [ pkgs.openssl ];
|
||||||
|
@ -302,11 +347,8 @@ in
|
||||||
};
|
};
|
||||||
in (
|
in (
|
||||||
[ { name = "acme-${cert}"; value = acmeService; } ]
|
[ { name = "acme-${cert}"; value = acmeService; } ]
|
||||||
++
|
++ optional cfg.preliminarySelfsigned { name = "acme-selfsigned-${cert}"; value = selfsignedService; }
|
||||||
(if cfg.preliminarySelfsigned
|
++ optional (data.activationDelay != null) { name = "acme-setlive-${cert}"; value = delayService; }
|
||||||
then [ { name = "acme-selfsigned-${cert}"; value = selfsignedService; } ]
|
|
||||||
else []
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
servicesAttr = listToAttrs services;
|
servicesAttr = listToAttrs services;
|
||||||
injectServiceDep = {
|
injectServiceDep = {
|
||||||
|
|
Loading…
Reference in a new issue