1. The problem I’m having:
I have a Caddy installation with circa 40 domains configured via Caddyfile. Since upgrading to v2.8.x, I am unable to access any of my sites due to an SSL error. For example:
$ curl -vL https://thomaspreece.net
* Trying 132.145.12.162:443...
* Connected to thomaspreece.net (132.145.12.162) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Unknown (21):
* TLSv1.3 (IN), TLS alert, internal error (592):
* error:0A000438:SSL routines::tlsv1 alert internal error
* Closing connection 0
curl: (35) error:0A000438:SSL routines::tlsv1 alert internal error
I downgraded to v2.7.6 in order to get all of my sites working again, so you won’t see this error if you try now.
Investigation showed that the problem seems to be that Caddy is unable to obtain Let’s Encrypt certificates. On v2.7.6 and below, it instead gets a certification from ZeroSSL and continues to function, but on v2.8.x this no longer works. I will look at configuring ZeroSSL on v2.8.x, but I want to resolve the issue with Let’s Encrypt first.
Looking at the logs shows repeated error messages of the following form:
caddy[150320]: {"level":"error","ts":1717338648.9697998,"logger":"tls.obtain","msg":"will retry","error":"[thomaspreece.net] Obtain: registering account [mailto:thomas@thomaspreece.net] with server: attempt 1: https://acme-v02.api.letsencrypt.org/acme/new-acct: HTTP 429 urn:ietf:params:acme:error:rateLimited - Error creating new account :: too many registrations for this IP: see https://letsencrypt.org/docs/too-many-registrations-for-this-ip/","attempt":1,"retrying_in":60,"elapsed":0.855544075,"max_duration":2592000}
It appears that the first 10 certificate requests succeed, and then all of the other ones (approx 30) fail. This is consistent with the document linked in the error message, which specifies that the rate limit is 10 accounts registered within 3 hours.
Presumably then Caddy is trying to register a new account for every certificate request, rather than creating one account and using it for every request.
To confirm that the SSL errors are caused by Caddy not being able to get certificates from Let’s Encrypt, I waited several hours for the rate limit timeout to expire, then added the following to my Caddyfile on v2.7.6 to force it to use Let’s Encrypt and not ZeroSSL:
{
acme_ca https://acme-v02.api.letsencrypt.org/directory
}
After restarting Caddy, I get the same SSL errors as above, and the same errors in the log file about the “too many registrations”. It seems that by asking it only to obtain certificates from Let’s Encrypt, it won’t use the existing ZeroSSL certificates, which I assume is expected behaviour.
I commented out the acme_ca line and restarted Caddy again, and all sites were once again available using the ZeroSSL certificates.
On searching for information about this error, I found a recommendation to look at the .caddy directory containing all of the certificates etc (which on my system is in fact /var/lib/caddy/.local/share/caddy). I found the subdirectories certificates/acme.zerossl.com-v2-dv90 (containing certificates for all sites) and certificates/acme-v02.api.letsencrypt.org-directory (containing the 10 certificates that Caddy was able to obtain before being rate limited). So it seems that Caddy is able to save the certificates correctly.
I also found a recommendation to delete the .caddy directory, to force Caddy to re-issue every certificate from scratch. After waiting several hours again for the Let’s Encrypt timeout to expire, I did this (actually, renamed the directory caddy to caddy-old) and restarted Caddy. Again I got the SSL errors on all sites - it seems it was now unable to fail over to ZeroSSL and obtain certificates that way, so all of the sites were unavailable.
I put the old caddy directory back in place and once again restarted Caddy, and confirmed that all sites were back up using the previously saved certificates.
I have also found other references online to people having issues with Caddy trying to create a new account for every certificate request, but all of these appear to be related to bugs that were fixed upwards of 5 years ago.
2. Error messages and/or full log output:
The log extract was too long to include in a post. It is available here.
The logs are with the acme_ca line mentioned above in place in the Caddyfile, to force it to request certificates from Let’s Encrypt. The timestamps don’t line up with the narrative of waiting several hours since then before trying other steps, because I re-ran that step today to get a fresh set of logs.
3. Caddy version:
$ caddy version
v2.7.6 h1:w0NymbG2m9PcvKWsrXO6EEkY9Ru4FJK8uQbYcev1p3A=
4. How I installed and ran Caddy:
a. System environment:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04.4 LTS
Release: 22.04
Codename: jammy
Caddy is installed via apt from the following repository:
$ cat /etc/apt/sources.list.d/caddy-stable.list
# Source: Caddy
# Site: https://github.com/caddyserver/caddy
# Repository: Caddy / stable
# Description: Fast, multi-platform web server with automatic HTTPS
deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main
deb-src [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main
b. Command:
$ sudo systemctl start caddy
c. Service/unit/compose file:
$ cat /usr/lib/systemd/system/caddy.service
# caddy.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target