- lib.attrsets.nameValuePair "acme-selfsigned-${k}" (lib.mkBefore { script =
- (lib.optionalString (builtins.elem "cert.pem" v.plugins) ''
- cp $workdir/server.crt ${config.security.acme.directory}/${k}/cert.pem
- chown '${v.user}:${v.group}' ${config.security.acme.directory}/${k}/cert.pem
- chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.directory}/${k}/cert.pem
- '') +
- (lib.optionalString (builtins.elem "chain.pem" v.plugins) ''
- cp $workdir/ca.crt ${config.security.acme.directory}/${k}/chain.pem
- chown '${v.user}:${v.group}' ${config.security.acme.directory}/${k}/chain.pem
- chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.directory}/${k}/chain.pem
- '')
- ; })
- ) config.security.acme.certs // {
- httpdProd.after = [ "acme-selfsigned-certificates.target" ];
- httpdProd.wants = [ "acme-selfsigned-certificates.target" ];
- httpdTools.after = [ "acme-selfsigned-certificates.target" ];
- httpdTools.wants = [ "acme-selfsigned-certificates.target" ];
- httpdInte.after = [ "acme-selfsigned-certificates.target" ];
- httpdInte.wants = [ "acme-selfsigned-certificates.target" ];
+ lib.attrsets.nameValuePair "acme-selfsigned-${k}" {
+ wantedBy = [ "acme-selfsigned-certificates.target" ];
+ script = lib.mkAfter ''
+ cp $workdir/server.crt ${config.security.acme.certs."${k}".directory}/cert.pem
+ chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/cert.pem
+ chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/cert.pem
+
+ cp $workdir/ca.crt ${config.security.acme.certs."${k}".directory}/chain.pem
+ chown '${v.user}:${v.group}' ${config.security.acme.certs."${k}".directory}/chain.pem
+ chmod ${if v.allowKeysForGroup then "750" else "700"} ${config.security.acme.certs."${k}".directory}/chain.pem
+ '';
+ }
+ ) config.security.acme.certs //
+ lib.attrsets.mapAttrs' (k: data:
+ lib.attrsets.nameValuePair "acme-${k}" {
+ after = lib.mkAfter [ "bind.service" ];
+ serviceConfig =
+ let
+ cfg = config.security.acme;
+ hashOptions = let
+ domains = builtins.concatStringsSep "," (
+ [ data.domain ] ++ (builtins.attrNames data.extraDomains)
+ );
+ certOptions = builtins.concatStringsSep "," [
+ (if data.ocspMustStaple then "must-staple" else "no-must-staple")
+ ];
+ in
+ builtins.hashString "sha256" (builtins.concatStringsSep ";" [ data.keyType domains certOptions ]);
+ accountsDir = "accounts-${data.keyType}";
+ lpath = "acme/${k}";
+ apath = "/var/lib/${lpath}";
+ spath = "/var/lib/acme/.lego/${k}";
+ fileMode = if data.allowKeysForGroup then "640" else "600";
+ dirFileMode = if data.allowKeysForGroup then "750" else "700";
+ globalOpts = [ "-d" data.domain "--email" data.email "--path" "." "--key-type" data.keyType ]
+ ++ lib.optionals (cfg.acceptTerms) [ "--accept-tos" ]
+ ++ lib.optionals (data.dnsProvider != null && !data.dnsPropagationCheck) [ "--dns.disable-cp" ]
+ ++ lib.concatLists (lib.mapAttrsToList (name: root: [ "-d" name ]) data.extraDomains)
+ ++ (if data.dnsProvider != null then [ "--dns" data.dnsProvider ] else [ "--http" "--http.webroot" config.myServices.certificates.webroot ])
+ ++ lib.optionals (cfg.server != null || data.server != null) ["--server" (if data.server == null then cfg.server else data.server)];
+ certOpts = lib.optionals data.ocspMustStaple [ "--must-staple" ];
+ runOpts = lib.escapeShellArgs (globalOpts ++ [ "run" ] ++ certOpts);
+ renewOpts = lib.escapeShellArgs (globalOpts ++
+ [ "renew" "--days" (builtins.toString cfg.validMinDays) ] ++
+ certOpts ++ data.extraLegoRenewFlags);
+ forceRenewOpts = lib.escapeShellArgs (globalOpts ++
+ [ "renew" "--days" "999" ] ++
+ certOpts ++ data.extraLegoRenewFlags);
+ keyName = builtins.replaceStrings ["*"] ["_"] data.domain;
+ in {
+ User = lib.mkForce "acme";
+ Group = lib.mkForce "acme";
+ WorkingDirectory = lib.mkForce spath;
+ StateDirectory = lib.mkForce "acme/.lego/${k} acme/.lego/${accountsDir}";
+ ExecStartPre =
+ let
+ script = pkgs.writeScript "acme-prestart" ''
+ #!${pkgs.runtimeShell} -e
+ install -m 0755 -o acme -g acme -d ${config.myServices.certificates.webroot}
+ '';
+ in
+ lib.mkForce "+${script}";
+ ExecStart = lib.mkForce (pkgs.writeScript "acme-start" ''
+ #!${pkgs.runtimeShell} -e
+ # lego doesn't check key type after initial creation, we
+ # need to check for him
+ if [ -L ${spath}/accounts -o -d ${spath}/accounts ]; then
+ if [ -L ${spath}/accounts -a "$(readlink ${spath}/accounts)" != ../${accountsDir} ]; then
+ ln -sfn ../${accountsDir} ${spath}/accounts
+ mv -f ${spath}/certificates/${keyName}.key ${spath}/certificates/${keyName}.key.old
+ fi
+ else
+ ln -s ../${accountsDir} ${spath}/accounts
+ fi
+ # check if domain changed: lego doesn't check by itself
+ if [ ! -e ${spath}/certificates/${keyName}.crt -o ! -e ${spath}/certificates/${keyName}.key -o ! -e "${spath}/accounts/acme-v02.api.letsencrypt.org/${data.email}/account.json" ]; then
+ ${pkgs.lego}/bin/lego ${runOpts}
+ elif [ ! -f ${spath}/currentDomains -o "$(cat ${spath}/currentDomains)" != "${hashOptions}" ]; then
+ ${pkgs.lego}/bin/lego ${forceRenewOpts}
+ else
+ ${pkgs.lego}/bin/lego ${renewOpts}
+ fi
+ '');
+ ExecStartPost =
+ let
+ script = pkgs.writeScript "acme-post-start" ''
+ #!${pkgs.runtimeShell} -e
+ install -m 0755 -o root -g root -d /var/lib/acme
+ install -m 0${dirFileMode} -o ${data.user} -g ${data.group} -d /var/lib/acme/${k}
+ cd /var/lib/acme/${k}
+
+ # Test that existing cert is older than new cert
+ KEY=${spath}/certificates/${keyName}.key
+ KEY_CHANGED=no
+ if [ -e $KEY -a $KEY -nt key.pem ]; then
+ KEY_CHANGED=yes
+ cp -p ${spath}/certificates/${keyName}.key key.pem
+ cp -p ${spath}/certificates/${keyName}.crt fullchain.pem
+ cp -p ${spath}/certificates/${keyName}.issuer.crt chain.pem
+ ln -sf fullchain.pem cert.pem
+ cat key.pem fullchain.pem > full.pem
+ echo -n "${hashOptions}" > ${spath}/currentDomains
+ fi
+
+ chmod ${fileMode} *.pem
+ chown '${data.user}:${data.group}' *.pem
+
+ if [ "$KEY_CHANGED" = "yes" ]; then
+ : # noop in case postRun is empty
+ ${data.postRun}
+ fi
+ '';
+ in
+ lib.mkForce "+${script}";
+ };
+ }
+ ) config.security.acme.certs //
+ {
+ httpdProd = lib.mkIf config.services.httpd.Prod.enable
+ { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
+ httpdTools = lib.mkIf config.services.httpd.Tools.enable
+ { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };
+ httpdInte = lib.mkIf config.services.httpd.Inte.enable
+ { after = [ "acme-selfsigned-certificates.target" ]; wants = [ "acme-selfsigned-certificates.target" ]; };