@@ -1,397 +0,0 @@
2−### https://github.com/NixOS/nixpkgs/blob/1d36ad6d16dbf1d3937f899a087a4360332eb141/nixos/modules/security/acme.nix
4−### to support new plugins in simp_le for ACMEv2 support.
5−### Changed lines are marked with a comment: ### CHANGED
7−{ config, lib, pkgs, ... }:
13− cfg = config.security.acme;
15− certOpts = { name, ... }: {
19− example = "/var/lib/acme/acme-challenges";
21− Where the webroot of the HTTP vhost is located.
22− <filename>.well-known/acme-challenge/</filename> directory
23− will be created below the webroot if it doesn't exist.
24− <literal>http://example.org/.well-known/acme-challenge/</literal> must also
25− be available (notice unencrypted HTTP).
32− description = "Domain to fetch certificate for (defaults to the entry name)";
36− type = types.nullOr types.str;
38− description = "Contact email address for the CA to be able to reach you.";
44− description = "User running the ACME client.";
50− description = "Group running the ACME client.";
53− allowKeysForGroup = mkOption {
57− Give read permissions to the specified group
58− (<option>security.acme.cert.<name>.group</option>) to read SSL private certificates.
65− example = "systemctl reload nginx.service";
67− Commands to run after new certificates go live. Typically
68− the web server and other servers using certificates need to
71− Executed in the same directory with the new certificate.
76− type = types.listOf (types.enum [
77− "cert.der" "cert.pem" "chain.pem" "external.sh"
78− "fullchain.pem" "full.pem" "key.der" "key.pem" "account_key.json" "account_reg.json" ### CHANGED
80− default = [ "fullchain.pem" "full.pem" "key.pem" "account_key.json" "account_reg.json" ]; ### CHANGED
82− Plugins to enable. With default settings simp_le will
83− store public certificate bundle in <filename>fullchain.pem</filename>,
84− private key in <filename>key.pem</filename> and those two previous
85− files combined in <filename>full.pem</filename> in its state directory.
89− activationDelay = mkOption {
90− type = types.nullOr types.str;
93− Systemd time span expression to delay copying new certificates to main
94− state directory. See <citerefentry><refentrytitle>systemd.time</refentrytitle>
95− <manvolnum>7</manvolnum></citerefentry>.
99− preDelay = mkOption {
103− Commands to run after certificates are re-issued but before they are
104− activated. Typically the new certificate is published to DNS.
106− Executed in the same directory with the new certificate.
110− extraDomains = mkOption {
111− type = types.attrsOf (types.nullOr types.str);
113− example = literalExample ''
115− "example.org" = "/srv/http/nginx";
116− "mydomain.org" = null;
120− A list of extra domain names, which are included in the one certificate to be issued, with their
121− own server roots if needed.
135− directory = mkOption {
136− default = "/var/lib/acme";
139− Directory where certs and other state will be stored by default.
143− validMin = mkOption {
145− default = 30 * 24 * 3600;
146− description = "Minimum remaining validity before renewal in seconds.";
149− renewInterval = mkOption {
153− Systemd calendar expression when to check for renewal. See
154− <citerefentry><refentrytitle>systemd.time</refentrytitle>
155− <manvolnum>7</manvolnum></citerefentry>.
159− preliminarySelfsigned = mkOption {
163− Whether a preliminary self-signed certificate should be generated before
164− doing ACME requests. This can be useful when certificates are required in
165− a webserver, but ACME needs the webserver to make its requests.
167− With preliminary self-signed certificate the webserver can be started and
168− can later reload the correct ACME certificates.
172− production = mkOption {
176− If set to true, use Let's Encrypt's production environment
177− instead of the staging environment. The main benefit of the
178− staging environment is to get much higher rate limits.
181− <literal>https://letsencrypt.org/docs/staging-environment</literal>
188− type = with types; attrsOf (submodule certOpts);
190− Attribute set of certificates to get signed and renewed.
192− example = literalExample ''
195− webroot = "/var/www/challenges/";
196− email = "foo@example.com";
197− extraDomains = { "www.example.com" = null; "foo.example.com" = "/var/www/foo/"; };
199− "bar.example.com" = {
200− webroot = "/var/www/challenges/";
201− email = "bar@example.com";
209− ###### implementation
211− (mkIf (cfg.certs != { }) {
213− systemd.services = let
214− services = concatLists servicesLists;
215− servicesLists = mapAttrsToList certToServices cfg.certs;
216− certToServices = cert: data:
218− cpath = lpath + optionalString (data.activationDelay != null) ".staging";
219− lpath = "${cfg.directory}/${cert}";
220− rights = if data.allowKeysForGroup then "750" else "700";
221− cmdline = [ "-v" "-d" data.domain "--default_root" data.webroot "--valid_min" cfg.validMin ]
222− ++ optionals (data.email != null) [ "--email" data.email ]
223− ++ concatMap (p: [ "-f" p ]) data.plugins
224− ++ concatLists (mapAttrsToList (name: root: [ "-d" (if root == null then name else "${name}:${root}")]) data.extraDomains)
225− ++ optionals (!cfg.production) ["--server" "https://acme-staging.api.letsencrypt.org/directory"];
227− description = "Renew ACME Certificate for ${cert}";
228− after = [ "network.target" "network-online.target" ];
229− wants = [ "network-online.target" ];
232− SuccessExitStatus = [ "0" "1" ];
233− PermissionsStartOnly = true;
238− path = with pkgs; [ simp_le systemd ];
240− mkdir -p '${cfg.directory}'
241− chown 'root:root' '${cfg.directory}'
242− chmod 755 '${cfg.directory}'
243− if [ ! -d '${cpath}' ]; then
246− chmod ${rights} '${cpath}'
247− chown -R '${data.user}:${data.group}' '${cpath}'
248− mkdir -p '${data.webroot}/.well-known/acme-challenge'
249− chown -R '${data.user}:${data.group}' '${data.webroot}/.well-known/acme-challenge'
254− simp_le ${escapeShellArgs cmdline}
257− echo "$EXITCODE" > /tmp/lastExitCode
263− if [ -e /tmp/lastExitCode ] && [ "$(cat /tmp/lastExitCode)" = "0" ]; then
264− ${if data.activationDelay != null then ''
268− if [ -d '${lpath}' ]; then
269− systemd-run --no-block --on-active='${data.activationDelay}' --unit acme-setlive-${cert}.service
271− systemctl --wait start acme-setlive-${cert}.service
273− '' else data.postRun}
275− # noop ensuring that the "if" block is non-empty even if
276− # activationDelay == null and postRun == ""
281− before = [ "acme-certificates.target" ];
282− wantedBy = [ "acme-certificates.target" ];
285− description = "Set certificate for ${cert} live";
286− path = with pkgs; [ rsync ];
291− rsync -a --delete-after '${cpath}/' '${lpath}'
293− postStop = data.postRun;
295− selfsignedService = {
296− description = "Create preliminary self-signed certificate for ${cert}";
297− path = [ pkgs.openssl ];
299− if [ ! -d '${cpath}' ]
302− chmod ${rights} '${cpath}'
303− chown '${data.user}:${data.group}' '${cpath}'
308− workdir="$(mktemp -d)"
311− openssl genrsa -des3 -passout pass:xxxx -out $workdir/ca.pass.key 2048
312− openssl rsa -passin pass:xxxx -in $workdir/ca.pass.key -out $workdir/ca.key
313− openssl req -new -key $workdir/ca.key -out $workdir/ca.csr \
314− -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com"
315− openssl x509 -req -days 1 -in $workdir/ca.csr -signkey $workdir/ca.key -out $workdir/ca.crt
318− openssl genrsa -des3 -passout pass:xxxx -out $workdir/server.pass.key 2048
319− openssl rsa -passin pass:xxxx -in $workdir/server.pass.key -out $workdir/server.key
320− openssl req -new -key $workdir/server.key -out $workdir/server.csr \
321− -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
322− openssl x509 -req -days 1 -in $workdir/server.csr -CA $workdir/ca.crt \
323− -CAkey $workdir/ca.key -CAserial $workdir/ca.srl -CAcreateserial \
324− -out $workdir/server.crt
326− # Copy key to destination
327− cp $workdir/server.key ${cpath}/key.pem
329− # Create fullchain.pem (same format as "simp_le ... -f fullchain.pem" creates)
330− cat $workdir/{server.crt,ca.crt} > "${cpath}/fullchain.pem"
332− # Create full.pem for e.g. lighttpd
333− cat $workdir/{server.key,server.crt,ca.crt} > "${cpath}/full.pem"
335− # Give key acme permissions
336− chown '${data.user}:${data.group}' "${cpath}/"{key,fullchain,full}.pem
337− chmod ${rights} "${cpath}/"{key,fullchain,full}.pem
341− PermissionsStartOnly = true;
347− # Do not create self-signed key when key already exists
348− ConditionPathExists = "!${cpath}/key.pem";
351− "acme-selfsigned-certificates.target"
354− "acme-selfsigned-certificates.target"
358− [ { name = "acme-${cert}"; value = acmeService; } ]
359− ++ optional cfg.preliminarySelfsigned { name = "acme-selfsigned-${cert}"; value = selfsignedService; }
360− ++ optional (data.activationDelay != null) { name = "acme-setlive-${cert}"; value = delayService; }
362− servicesAttr = listToAttrs services;
363− injectServiceDep = {
364− after = [ "acme-selfsigned-certificates.target" ];
365− wants = [ "acme-selfsigned-certificates.target" "acme-certificates.target" ];
369− (if config.services.nginx.enable then { nginx = injectServiceDep; } else {}) //
370− (if config.services.lighttpd.enable then { lighttpd = injectServiceDep; } else {});
372− systemd.timers = flip mapAttrs' cfg.certs (cert: data: nameValuePair
375− description = "Renew ACME Certificate for ${cert}";
376− wantedBy = [ "timers.target" ];
378− OnCalendar = cfg.renewInterval;
379− Unit = "acme-${cert}.service";
382− RandomizedDelaySec = "1h";
387− systemd.targets."acme-selfsigned-certificates" = mkIf cfg.preliminarySelfsigned {};
388− systemd.targets."acme-certificates" = {};
394− maintainers = with lib.maintainers; [ abbradar fpletz globin ];
395− #doc = ./acme.xml; ### CHANGED