Certbot "failed to authenticate some domains": read the Type, then fix DNS, port 80 or the path
Fix Certbot "failed to authenticate some domains": read the error type, then fix DNS records, an IPv6 AAAA record, a closed port 80, the webroot, Cloudflare and CAA.
by OhSudo ··
Checked on real software: Certbot · November 2026How we check
Not sure this is your cause?Find it step by step: Website down →
Part of a learning path:Web servers: nginx and HTTPS in production
Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems: Domain: example.com Type: unauthorized Detail: 203.0.113.10: Invalid response from http://example.com/.well-known/acme-challenge/abc123: 404To issue a certificate, Let’s Encrypt has to confirm that you control the domain. With the usual method, Certbot places a small file on your server, and Let’s Encrypt fetches it from the internet, over port 80. Your certificate depends on that request working.
The two lines to read are Type and Detail. They say how the check failed, and each type has its own cause.
- Let's Encryptlooks up your domainconnects to
- Your server, port 80DNS, firewall, proxyfetches(fails)
- The challenge file/.well-known/acme-challenge/…(breaks here)
TL;DR
Reproduce the check yourself, from outside your server:
dig +short A example.comdig +short AAAA example.comcurl -I http://example.com/.well-known/acme-challenge/testDo the addresses belong to your server? Does curl reach it, with a 404 from your web server? Fix what doesn’t, then test without using up your limits:
sudo certbot certonly --nginx --dry-run -d example.com1. What the type means
| Type | Means | Go to |
|---|---|---|
dns |
The name doesn’t resolve | Section 2 |
connection |
Let’s Encrypt reached the address, but got no connection | Section 3 |
unauthorized |
It connected, but got the wrong answer | Section 4 |
caa |
A DNS record forbids this certificate authority | Section 6 |
The full log is in /var/log/letsencrypt/letsencrypt.log.
2. Type: dns
Type: dnsDetail: DNS problem: NXDOMAIN looking up A for example.com - check that a DNS record exists for this domainThe record doesn’t exist, or it hasn’t spread yet. Ask a public resolver instead of your local one:
dig +short A example.com @1.1.1.1dig +short NS example.com @1.1.1.1Empty means there’s no record. Check for www too: certbot -d example.com -d www.example.com needs both to resolve. After a new record or a name server change, wait a little and retry.
SERVFAIL looking up is different: the DNS servers are failing, often because of broken DNSSEC. A check such as dnsviz.net shows where.
3. Type: connection
Type: connectionDetail: 203.0.113.10: Fetching http://example.com/.well-known/acme-challenge/abc123: Timeout during connect (likely firewall problem)Port 80 isn’t reachable from the internet. It has to be open to everyone, even if your site is HTTPS only. Let’s Encrypt doesn’t publish the addresses it checks from, and uses several on purpose, so you can’t allow only those.
# On the server: is something listening?sudo ss -tlnp | grep ':80 '
# Ubuntu / Debiansudo ufw allow 80/tcp
# RHEL / Rocky / AlmaLinuxsudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --reloadIn the cloud, check the security group too, as it’s outside the machine. Then test from another network, such as your phone’s data, since a test from the server itself proves little. Details in “Connection timed out” vs “Connection refused”. The Port Lookup explains what port 80 is for.
Can’t open port 80, or your server is on a private network? Use the DNS challenge (section 7). Some home internet providers also block port 80.
Connection refused here means nothing listens on that port: start the web server. If something else has taken the port, see address already in use.
4. Type: unauthorized
Type: unauthorizedDetail: 203.0.113.10: Invalid response from http://example.com/.well-known/acme-challenge/abc123: 404Let’s Encrypt reached a server, and didn’t get the file. First look at the address in Detail. If it isn’t your server’s, the DNS record is wrong, or there’s a stale one.
An IPv6 record is the sneaky one. Let’s Encrypt prefers IPv6 when a domain has an AAAA record:
dig +short AAAA example.comIf it points at an old machine, or the web server doesn’t listen on IPv6, fix the record or remove it. In Nginx, this is the listen [::]:80; line.
Another site answered. With several sites on one server, the request may land on the default one. Check that server_name includes this exact domain. Then see what happens with a test file, using --webroot’s folder:
sudo mkdir -p /var/www/html/.well-known/acme-challengeecho ok | sudo tee /var/www/html/.well-known/acme-challenge/testcurl -i http://example.com/.well-known/acme-challenge/testIt should answer 200 and ok. Remove the file afterwards. Failing that:
- A redirect that loses the path. Redirecting to HTTPS is fine, as Let’s Encrypt follows it, but a redirect to the home page isn’t.
- A rule that blocks hidden paths.
location ~ /\. { deny all; }also denies.well-known, and gives a403. Allow it first:
location ^~ /.well-known/acme-challenge/ { root /var/www/html; default_type text/plain;}- An application that catches every URL. A
proxy_passon/sends it to your app, which answers 404. The block above fixes this as well, since^~wins over other locations. - The wrong webroot.
--webroot -whas to be the folder this site really serves from.
The Nginx Config Generator avoids these path problems another way: its steps use Certbot’s --standalone mode, which answers the challenge itself while Nginx is stopped for a few seconds.
5. Behind Cloudflare or another proxy
With Cloudflare’s proxy on (orange cloud), dig shows Cloudflare’s addresses, so the request passes through it. It usually works, but these cause trouble: Always Use HTTPS with an SSL mode that fails, and firewall rules or bot checks answering the challenge request. Cloudflare’s Full (strict) mode can also refuse an expired certificate on your server, which then can’t renew.
The simplest options are to switch the record to DNS only (grey cloud) while you get the certificate, or use the DNS challenge. Its plugin never touches your web server:
sudo apt install python3-certbot-dns-cloudflaresudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/cloudflare.ini -d example.comKeep that credentials file private with chmod 600, using a token limited to this one zone. If the site loops afterwards, see ERR_TOO_MANY_REDIRECTS.
6. Type: caa
Type: caaDetail: CAA record for example.com prevents issuanceA CAA record lists who may issue certificates for the domain, and Let’s Encrypt isn’t on it:
dig +short CAA example.comAdd it next to the others, in your DNS provider: example.com. CAA 0 issue "letsencrypt.org".
7. The DNS challenge
It proves control with a TXT record, so no port needs opening. It’s also the only way to get a wildcard certificate:
sudo certbot certonly --manual --preferred-challenges dns -d '*.example.com' -d example.comDone by hand, --manual doesn’t renew by itself. For a certificate that should renew on its own, use the plugin for your DNS provider.
8. Limits, and stop retrying
Repeated failures run into Let’s Encrypt’s rate limits, and then you get this instead, whatever you fix:
too many failed authorizations (5) for "example.com" in the last 1h0m0sSo test with the staging server, which has much higher limits and issues certificates that browsers don’t trust:
sudo certbot certonly --nginx --dry-run -d example.com -d www.example.comRun the real one when that passes. Then see what’s installed, and when it renews:
sudo certbot certificatessystemctl list-timers | grep certbotShell, we have a problem!
Similar, but different: Could not bind TCP port 80 comes from --standalone when your web server already holds the port: use --nginx, --apache or --webroot instead. Could not automatically find a matching server block means Nginx has no server_name for this domain. And an error from a program that uses the certificate, such as unable to get local issuer certificate, is usually a missing chain: use fullchain.pem, not cert.pem. If yours has run out, see certificate has expired. too many certificates already issued is Let’s Encrypt’s weekly limit.
Found this useful? Share it.
Found a mistake? Let us know at contact@ohsudo.com.