The acmedns backend consumes a ACME_DNS_STORAGE_PATH environment
variable.
Upstream does treat this file as mutable (if you create or delete
accounts through the CLI, it would update it. We don't do this in our
module).
But the possibility for edits is probably why they didn't go with
`ACME_DNS_CONFIG` env var for the contents (as they'd be read-only), or
a `ACME_DNS_CONFIG_FILE`. (And the fact that a
`ACME_DNS_STORAGE_PATH_FILE` env var with questionable usability exists
is due to this logic being generic for most env vars).
So instead of fighting upstream over this, let's simply make our module
assertion also accept `_PATH` suffixes for `credentialFiles`.
Fixes#344684.
Per https://github.com/NixOS/nixpkgs/issues/96006, this does not work as
expected.
The warning trace will be emitted regardless of whether the option is
set, rendering it pointless. It does not work at the top-level either
(i.e. as `"security" "acme" "defaults" "credentialsFile"`), As such,
remove it entirely.
Situations where systemd-tmpfiles rules aren't applied but
acme-$name.service is rerun are quite unlikely, so it should be fine to
remove the mkdir completely.
Up to now, the webroot mechanism wasn't usable without extra steps
when the certificate was not intended for the web server. In my case,
I wanted to obtain a certificate for use in other services from a
private CA, but validate via a webroot served by nginx. The (sensibly!)
restrictive umask of acme-$name.service led to the webroot being created
with o-rx permissions, which meant that nginx could not serve the
webroot and the certificate could not be obtained.
This retains the mkdir invocation as a best-effort attempt to create the
webroot if for example the state has been cleared since systemd-tmpfiles
setup, but relies primarily on systemd-tmpfiles to create the webroots
with appropriate permissions.
With Lego since 4.25.0 instead of --days we can pass --dynamic to pick
the renewal date based on a fraction of its total validity duration.
This provides a reasonable default that accomodates varying certificate
validy durations we're going to be seeing through the profile option and
LE's plans to reduce the default validity duration in multiple steps down
to 45 days in 2028.
This changes changes the default valid duration to null to enable dynamic
renewal calculation. To that end the expiration skip function gained the
ability to calculate the total and remaining duration and to apply the
correct remainder based on the certificates total duration.
Let's Encrypt does not require email addreses any longer, so we should
allow users not to provide any.
Unsetting the email adress will change the account hash and Lego will
start using a dummy email address instead. The address is hardcoded in
the Lego source code in the userIDPlaceholder constant.
We then verify in tests that changing between no email address and the
placeholder address does not create a new account nor rotate the previous
certificate.
This is supported since Lego 4.30.1.
https://github.com/go-acme/lego/commit/bc163db9edd23bbfc3521086c0b570f468b9a87b
Currently ReadWritePaths is only sufficiently specificed for
acme-order-renew-${domain}.service, and not acme-${domain}.service. This
results in service failure if specifying the webroot outside of
/var/lib/acme, for example /var/www/challenges:
acme-example.com-start[1379]: + mkdir -p /var/www/challenges//.well-known/acme-challenge
acme-example.com-start[1382]: mkdir: cannot create directory ‘/var/www/challenges//.well-known’: Read-only file system
systemd[1]: acme-example.com.service: Main process exited, code=exited, status=1/FAILURE
Fix it by adding the webroots to ReadWritePaths in the common
serviceConfig, where it can affect both acme-order-renew-${domain}.service
AND acme-${domain}.service.
Avoid adding subdirs of existing ReadWritePaths entries, because
otherwise systemd will fail to set up the services, for example:
acme-zeroconf.example.test.service: Failed to set up mount namespacing: /run/acme: No such file or directory
(Confusingly, the path shown in the error message isn't necessarily
related to the problematic path.)
Extracts the fixed 24h random delay into a configurable option suitable
for other profiles, that require different renew intervals.
With the introduction of LE's shortlived profile a fixed random delay
does not cut it anymore, as it will delay short renew intervals by up
to a day before they are run. In an ideal world we could make the delay
proportional to the renew interval, but the `OnCalendar=` format is a bit
too complicated.
The previous setup caused all renewal units to be triggered upon
ever so slight changes in config. In larger setups (100+ certificates)
adding a new certificate caused high system load and/or large memory
consumption issues. The memory issues are already a alleviated with
the locking mechanism. However, this then causes long delays upwards
of multiple minutes depending on individual runs and also caused
superfluous activations.
In this change we streamline the overall setup of units:
1. The unit that other services can depend upon is 'acme-{cert}.service'.
We call this the 'base unit'. As this one as `RemainAfterExit` set
the `acme-finished-{cert}` targets are not required any longer.
2. We now always generate initial self-signed certificates to simplify
the dependency structure. This deprecates the `preliminarySelfsigned`
option.
3. The `acme-order-renew-{cert}` service gets activated after the base
unit and services using certificates have started and performs all acme
interactions. When it finishes others services (like web servers) will
be notified through the `reloadServices` option or they can use
`wantedBy` and `after` dependencies if they implement their own reload
units.
The renewal timer also triggers this unit.
4. The timer unit is explicitly blocked from being started by s-t-c.
5. Permission management has been cleaned up a bit: there was an
inconsistency between having the .lego files set to 600 vs 640
on the exposed side. This is unified to 640 now.
6. Exempt the account target from being restarted by s-t-c. This will
happen automatically if something relevant to the account changes.
Split tests up based on certain use cases:
- http01-builtin: Tests most functionality of the core module, such
as the systemd and hashing components, whilst utilising lego's built
in http01 resolution mechanis.
- dns01: Tests only that DNS01 renewal works as expected.
- nginx: Tests nginx compatability
- httpd: Tests httpd compatability
- caddy: Tests caddy compatability
Over time, we added a lot of setup services to the ACME module, namely:
- acme-selfsigned-ca.service: Creates the selfsigned CA certificates
used to generate selfsigned certs for each configured cert.
- acme-fixperms.service: Ensures permissions correctness on certs after
system configuration changes.
- acme-lockfiles.service: Create lockfiles used to implement
maxConcurrentRenewals.
These numerous setup services complicated the dependency chain for any
cert renewal, and also made it difficult to track responsibility for
specific setup steps, for example, creating /var/lib/acme or setting
permissions of shared folders.
This change proposes a new acme-setup.service which encapsulates the
functionality of the previous 3 services into one. The service is still
defined in 3 separate chunks (using lib.mkMerge) which allows us to
keep a logical separation between each step and preserve some
optionality in the features.
The result is a generally simplified definition of systemd unit
dependencies and an obvious entrypoint for future setup extensions.
This change is to support LEGO's capability to spawn an external process that
solves the DNS-01 challenge. In particular, this enables a setup where LEGO
runs a shell script that uses nsd-control to add an appropriate zone to a
local NSD instance.
It was being created with the default home permissions of 700, and then
set to 755 at runtime by something either some script or systemd as
part of service startup.
It worked fine without sysusers, but when it's enabed with:
systemd.sysusers.enable = true;
systemd-tmpfiles is resetting permissions on each activation, which
breaks, for example, nginx reload, because it cannot load certificates
anymore, because it doesn't have any access to `/var/lib/acme`.
Fix this by setting `homeMode = "755";` explicitely so that it's set to
the final value from the beginning.
I have no idea what this escape sequence even is, but it breaks the nix parser with cryptic errors if not used in a comment.
A friend let me know MacOS is prone to input weird spaces, not sure if that is the source.
Candidates were located and created with:
chr="$(echo -e '\xc2\xa0')"; rg -F "$chr" -l | xe sd -F "$chr" " "
There are some examples left, most being example output from `tree` in various markdown documents, some patches which we can't really touch, and `pkgs/tools/nix/nixos-render-docs/src/tests/test_commonmark.py` which I'm not sure if should be addressed