Caddy’s ability to automatically provision and renew TLS certificates is one of its killer features, and ZeroSSL is a fantastic ACME provider that integrates seamlessly.
Here’s ZeroSSL in action, serving a Caddy site with a certificate obtained via ACME:
curl -v https://your-domain.com
You’ll see * Server certificate: followed by details about the certificate issued by ZeroSSL.
How Caddy and ZeroSSL Work Together
Caddy acts as an ACME client. When it detects that a site needs a certificate (either it doesn’t have one, or the current one is nearing expiration), it initiates an ACME challenge with a chosen ACME server, in this case, ZeroSSL. The most common challenge type Caddy uses is HTTP-01, where Caddy temporarily serves a specific file at a specific URL on the domain that needs the certificate. The ACME server (ZeroSSL) then queries that URL to verify that Caddy controls the domain. If successful, ZeroSSL issues a certificate, which Caddy then downloads and configures for use.
The primary levers you control are within your Caddyfile:
your-domain.com {
# ... your site configuration ...
tls {
ca https://acme.zerossl.com/v2/DV90
}
}
The tls directive is where the magic happens. By default, Caddy uses Let’s Encrypt’s production endpoint. To use ZeroSSL, you explicitly tell Caddy to use ZeroSSL’s ACME CA endpoint: ca https://acme.zerossl.com/v2/DV90. This is the production endpoint for ZeroSSL’s Domain Validated certificates.
Common ZeroSSL Configuration Pitfalls
-
Incorrect CA Endpoint:
- Diagnosis: Caddy logs will show errors like
ACME server not foundorno such host. - Cause: The
cadirective is either missing, misspelled, or pointing to an old/invalid ZeroSSL endpoint. ZeroSSL has evolved its endpoints. - Fix: Ensure your
tlsblock explicitly statesca https://acme.zerossl.com/v2/DV90. - Why it works: This tells Caddy exactly which ACME server to talk to for certificate issuance.
- Diagnosis: Caddy logs will show errors like
-
Rate Limiting:
- Diagnosis: Caddy logs will show
ACME server returned error: <HTTP status code 429>andRate limit exceeded. - Cause: You’ve made too many ACME requests (e.g., restarting Caddy repeatedly, trying to get certs for many domains rapidly) within ZeroSSL’s rate limits.
- Fix: Wait for the rate limit to expire (typically an hour for duplicate certificate requests, longer for other limits). If you need to test, use ZeroSSL’s staging endpoint:
ca https://acme.zerossl.com/v2/DV90/staging. Note that staging certificates are not trusted by browsers. - Why it works: This respects the ACME server’s policy to prevent abuse and ensure fair access for all users.
- Diagnosis: Caddy logs will show
-
Firewall Blocking ACME Challenges:
- Diagnosis: Caddy logs will indicate challenges failing, often with timeouts or connection refused errors when ZeroSSL tries to reach your server on port 80.
- Cause: An external firewall (network firewall, cloud security group,
ufw,firewalld) is blocking inbound traffic on port 80. Caddy uses HTTP-01 challenges by default, which require port 80 to be accessible from the internet. - Fix: Ensure port 80 is open to inbound traffic from
0.0.0.0/0(or at least from ZeroSSL’s IP ranges, though0.0.0.0/0is simpler for HTTP-01). Forufw:sudo ufw allow 80/tcp. Forfirewalld:sudo firewall-cmd --permanent --add-service=http && sudo firewall-cmd --reload. - Why it works: This allows ZeroSSL’s validation servers to connect to your Caddy instance on port 80 to perform the HTTP-01 challenge.
-
Incorrect DNS Records:
- Diagnosis: Caddy logs show
ACME server validation failedorIncorrect TXT record. - Cause: If you were using DNS-01 challenges (less common with Caddy’s defaults but possible), your DNS provider’s API integration is misconfigured, or the TXT records Caddy attempted to create were incorrect or not propagated.
- Fix: For HTTP-01, ensure your domain’s A/AAAA records point to the IP address where Caddy is running and accessible on port 80. For DNS-01, verify your DNS provider credentials and that Caddy can correctly create/delete TXT records.
- Why it works: ACME validation relies on proving control over the domain. For HTTP-01, this is done by responding to a web request; for DNS-01, it’s by proving control of DNS records.
- Diagnosis: Caddy logs show
-
Caddy Not Running or Not Listening on Port 80:
- Diagnosis: ZeroSSL validation fails with connection timeouts.
- Cause: Caddy isn’t running, or it’s configured to listen on a different port for HTTP challenges (e.g., if you manually specified
http://:8080in a previous Caddyfile iteration and didn’t revert, or if another process is using port 80). - Fix:
- Start Caddy:
sudo systemctl start caddy(or equivalent for your OS). - Check if Caddy is listening:
sudo ss -tulnp | grep ':80'should showcaddylistening on port 80. - If port 80 is in use:
sudo lsof -i :80to find the process and stop it, or reconfigure Caddy to use a different port (e.g.,0.0.0.0:8080) and ensure that port is forwarded to port 80 on your actual server if necessary (though direct port 80 is standard for ACME).
- Start Caddy:
- Why it works: Caddy must be actively listening on port 80 to respond to the HTTP-01 challenge requests from ZeroSSL.
-
ZeroSSL Account Issues (Less Common with Caddy’s Direct Usage):
- Diagnosis: Persistent ACME errors, or ZeroSSL dashboard showing no successful orders.
- Cause: In rare cases, there might be an issue with the underlying ZeroSSL account or API key if you were trying to use specific ZeroSSL API features directly. Caddy’s ACME client usually handles this transparently.
- Fix: Ensure you’re not hitting account-specific limits on ZeroSSL’s platform. If you’ve previously registered an account with ZeroSSL and are trying to use its API directly (which Caddy abstracts), ensure your API key is valid. For standard Caddy usage with ZeroSSL’s CA endpoint, this is rarely an issue.
- Why it works: ACME protocol relies on communication and validation between the client (Caddy) and the CA (ZeroSSL). Any breakdown in this communication channel, including account-level restrictions, will prevent certificate issuance.
The next hurdle you’ll likely encounter after successfully configuring ZeroSSL is understanding and managing certificate renewals, especially if you’re using custom ACME endpoints or need to interact with ZeroSSL’s dashboard for more advanced features.