nixos/apache: not "before" ACME certs using DNS validation

Relax dependency with certs that are validated via DNS challenge since
we know the HTTP server is not required for that validation.
This allows marking the server's service as depending on the cert.
This commit is contained in:
ThinkChaos 2024-08-21 17:46:30 -04:00
parent 807e9154dc
commit b99d3a4f8b
No known key found for this signature in database

View File

@ -33,7 +33,9 @@ let
certName = if hostOpts.useACMEHost != null then hostOpts.useACMEHost else hostOpts.hostName; certName = if hostOpts.useACMEHost != null then hostOpts.useACMEHost else hostOpts.hostName;
}) (filter (hostOpts: hostOpts.enableACME || hostOpts.useACMEHost != null) vhosts); }) (filter (hostOpts: hostOpts.enableACME || hostOpts.useACMEHost != null) vhosts);
dependentCertNames = unique (map (hostOpts: hostOpts.certName) acmeEnabledVhosts); vhostCertNames = unique (map (hostOpts: hostOpts.certName) acmeEnabledVhosts);
dependentCertNames = filter (cert: certs.${cert}.dnsProvider == null) vhostCertNames; # those that might depend on the HTTP server
independentCertNames = filter (cert: certs.${cert}.dnsProvider != null) vhostCertNames; # those that don't depend on the HTTP server
mkListenInfo = hostOpts: mkListenInfo = hostOpts:
if hostOpts.listen != [] then if hostOpts.listen != [] then
@ -644,7 +646,7 @@ in
inherit (cfg) group user; inherit (cfg) group user;
cert = config.security.acme.certs.${name}; cert = config.security.acme.certs.${name};
groups = config.users.groups; groups = config.users.groups;
}) dependentCertNames; }) vhostCertNames;
warnings = warnings =
mapAttrsToList (name: hostOpts: '' mapAttrsToList (name: hostOpts: ''
@ -747,8 +749,10 @@ in
systemd.services.httpd = { systemd.services.httpd = {
description = "Apache HTTPD"; description = "Apache HTTPD";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
wants = concatLists (map (certName: [ "acme-finished-${certName}.target" ]) dependentCertNames); wants = concatLists (map (certName: [ "acme-finished-${certName}.target" ]) vhostCertNames);
after = [ "network.target" ] ++ map (certName: "acme-selfsigned-${certName}.service") dependentCertNames; after = [ "network.target" ]
++ map (certName: "acme-selfsigned-${certName}.service") vhostCertNames
++ map (certName: "acme-${certName}.service") independentCertNames; # avoid loading self-signed key w/ real cert, or vice-versa
before = map (certName: "acme-${certName}.service") dependentCertNames; before = map (certName: "acme-${certName}.service") dependentCertNames;
restartTriggers = [ cfg.configFile ]; restartTriggers = [ cfg.configFile ];
@ -789,8 +793,8 @@ in
# which allows the acme-finished-$cert.target to signify the successful updating # which allows the acme-finished-$cert.target to signify the successful updating
# of certs end-to-end. # of certs end-to-end.
systemd.services.httpd-config-reload = let systemd.services.httpd-config-reload = let
sslServices = map (certName: "acme-${certName}.service") dependentCertNames; sslServices = map (certName: "acme-${certName}.service") vhostCertNames;
sslTargets = map (certName: "acme-finished-${certName}.target") dependentCertNames; sslTargets = map (certName: "acme-finished-${certName}.target") vhostCertNames;
in mkIf (sslServices != []) { in mkIf (sslServices != []) {
wantedBy = sslServices ++ [ "multi-user.target" ]; wantedBy = sslServices ++ [ "multi-user.target" ];
# Before the finished targets, after the renew services. # Before the finished targets, after the renew services.
@ -801,7 +805,7 @@ in
restartTriggers = [ cfg.configFile ]; restartTriggers = [ cfg.configFile ];
# Block reloading if not all certs exist yet. # Block reloading if not all certs exist yet.
# Happens when config changes add new vhosts/certs. # Happens when config changes add new vhosts/certs.
unitConfig.ConditionPathExists = map (certName: certs.${certName}.directory + "/fullchain.pem") dependentCertNames; unitConfig.ConditionPathExists = map (certName: certs.${certName}.directory + "/fullchain.pem") vhostCertNames;
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
TimeoutSec = 60; TimeoutSec = 60;