Repository navigation
A release of fixes, from a review of 1.7.0 against the RFCs, the certificate authorities' own source and the cloud APIs. Every package changed. Read Upgrading before deploying: two of the changes need something from you.
Renewal
- A certificate issued to a previous ACME account is renewed again. The account is keyed by the email address and the certificate by its domains, so changing
EmailAddress, or losing the account key, left a certificate that a new account had to renew. Let's Encrypt and Pebble refuse a renewal hint (replaces) that names another account's certificate with 403 unauthorized, and onlyalreadyReplacedwas handled, so renewal failed on every attempt, past expiry, until a restart. The order is now placed again without the hint, and event 148 says so. - Changing
DomainNameskeeps the names that stayed online. A changed list found nothing stored and served the self-signed fallback for every name until a certificate for the new set was issued, which never happened while a new name could not validate. The previous certificate is now served for the names it covers while the new set is ordered, the health check reports Degraded meanwhile, and event 149 says what happened. AutoHttps keeps a copy of the latest certificate from each authority for this: thelatest-files in the storage directory. - Changing
KeyAlgorithmreplaces the certificate straight away instead of at its next renewal (event 151). - The stored ACME account is looked up instead of registered again on every start, so the external account binding is not sent again. Google Trust Services binding keys are single use and expire after seven days, so a restart no longer depends on the authority ignoring a spent key.
- A finalize whose response was lost is no longer sent a second time. That used to report a certificate being issued as a failure and order a duplicate.
- A lock that cannot be taken counts as a failed attempt. A storage directory that cannot be written now reaches the failure count, the overdue escalation (event 147), the listeners and the diagnostics.
- Picking up a certificate another replica published clears this replica's failure count and backoff.
- An issued certificate is saved even when shutdown starts during the write.
- The stored certificate is loaded before Kestrel accepts connections, so the first handshakes after a restart no longer get the fallback.
Platforms and storage
- macOS loads certificates. The library used
EphemeralKeySeteverywhere except Windows, the macOS loader refuses it, and so nothing loaded there while each retry ordered and lost a certificate. CI now includes macOS. - On Linux and macOS the storage directory is created owner-only whichever component creates it first, and key files are created at 0600 rather than changed to it after the write.
- On Windows, a store write blocked by another open handle is retried, and if the certificate still cannot be written the previous key is put back, so the stored pair always matches.
Cloud packages
- Route 53 and Azure DNS add their value to the TXT record set and later remove only that value, instead of replacing the set and deleting all of it. Another client ordering for the same name no longer loses its record. Azure writes are conditional on the record set's etag.
- Route 53 waits for each change to reach
INSYNC, for up to two minutes, before validation is requested. - Cloudflare and Route 53 choose the most specific zone, so a delegated subzone is used even after its parent was cached.
UseRedisalso registers the newRedisDistributedLock, so replicas sharing Redis no longer all order at the same moment, and the application starts while Redis is down instead of failing as the host starts.- Key Vault recovers a soft-deleted secret before writing it.
- Route 53 and Azure refuse partial credentials at startup instead of falling back to the default credential chain. On Azure,
ClientIdon its own now selects that user-assigned managed identity.
Diagnostics and messages
- A DNS-over-HTTPS answer that is not JSON counts as no answer, instead of failing the order or the diagnostics report.
- The DNS check no longer demands an address for a name validated by dns-01, and passes a name that has only an AAAA record.
- The CAA check reads the RFC 8657
validationmethodsandaccounturiparameters, which Let's Encrypt enforces and every public authority must from 2027-03-15, reports a CAA lookup that fails, and warns about an unknown property marked critical. - The authority's
explanationURLfor a renewal window is logged (event 155), and error messages keep a problem's subproblems andinstance, so a failure across several names names all of them. - P-384 signing requests are signed with SHA-384, which AWS Certificate Manager requires.
Upgrading
- Route 53 now needs the
route53:GetChangepermission, because the provider waits for each change to apply. Without it every dns-01 order fails, so add it to the IAM policy before upgrading. - Partly configured cloud credentials stop the application at startup, with an error naming the options: only one of
AccessKeyIdandSecretAccessKeyfor Route 53, or an incomplete Azure service principal. Before, the application signed in through the default chain as whatever identity that found. UseRedisregisters a lock. If you supplied your own withUseDistributedLock<T>(), register it afterUseRedis, or the Redis lock replaces it.- The interval, delay and timeout options are limited to 30 days, and a longer value fails options validation at startup. Before, a wait of more than about 49.7 days made the timer throw later, inside the renewal loop.
- When
RequireCertificateOnStartupstops the application, the process now exits with code 1, so restart policies such as systemd'sRestart=on-failurerestart it. - Removing a domain keeps the current certificate until its ordinary renewal, since it still covers the remaining names. Adding one orders straight away, as before.
- A deactivated ACME account is reported rather than replaced. Every attempt fails with the authority's reason (event 110). Remove the stored account key to register a new account.
Packages
AutoHttps1.8.0AutoHttps.Redis1.2.0AutoHttps.Route531.1.0AutoHttps.Azure1.1.0AutoHttps.Cloudflare1.0.1
The cloud packages are tested against fakes of Route 53, Azure DNS, Key Vault and Cloudflare that follow their documented behaviour, not against the live services.