Background
This is a complex issue and the interplay between various technologies such as DNS, HTTP Challenge, website (Apache / NGINX), permissions, and redirections can make the problem incredibly hard to troubleshoot.
Tips
Carefully evaluate the error. Specifically looks for the `Invalid response from` string as you might be getting a completely different reply that you would expect.
Original Article with Amendments
On a Virtualmin server, refreshing a Let’s Encrypt certificate gives the error. We have highlighted in bold the note to watch for in the output as there could be many different failed outcomes for Let’s Encrypt, e.g.
- 404
- Unauthorized
This log file covers Unauthorized
Requesting a certificate for domain.com from Let's Encrypt .. .. request failed : Web-based validation failed : Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator webroot, Installer None Cert is due for renewal, auto-renewing... Renewing an existing certificate Performing the following challenges: http-01 challenge for domain.com Using the webroot path /home/domain.com/public_html for all unmatched domains. Waiting for verification... Cleaning up challenges Failed authorization procedure. domain.com (http-01): urn:ietf:params:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://domain.com/.well-known/acme-challenge/A3oiNXYoxM6Bwze9iTWC0KoxCf-JzF49ozlwJpVzucc [52.215.112.96]: "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-w" IMPORTANT NOTES: - The following errors were reported by the server: Domain: domain.com Type: unauthorized Detail: Invalid response from http://domain.com/.well-known/acme-challenge/A3oiNXYoxM6Bwze9iTWC0KoxCf-JzF49ozlwJpVzucc [x.y.112.96]: "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-w" To fix these errors, please make sure that your domain name was entered correctly and the DNS A/AAAA record(s) for that domain contain(s) the right IP address.
The error was because the NGINX file had directives that wouldn’t let Let’s Encrypt complete. A radical approach worked by refreshing the NGINX configuration but Edit Virtual Server
, remove NGINX and SSL NGINX and then re-add. However, the next time this happened another path was chosen:
Revert to Certbot when all else fails
For this specific instance Certbot was chosen instead. One possible reason why Certbot might work better from the command line is this:
Using the webroot path /home/domain.com/public_html for all unmatched domains.
If you’ve modified your webroot, which is often the case for a YII or Laravel application, that path will not be valid anymore.
So instead of using the UI, we used the following command logged in as Root:
sudo certbot --nginx -d domainname.com
To get Certbot to automatically renew, see this article:
https://certbot.eff.org/docs/using.html?highlight=renew#automated-renewals
How Virtualmin’s Let’s Encrypt HTTP Challenge Works
To gain understanding of Let’s Encrypt’s algorithm, it’s broadly like this:
- Trigger a new SSL install
- The source server receives the challenge and write a temporary file
- Web server contacts the Let’s Encrypt Server to initiate request
- Let’s Encrypt connects back to the source server to see if the challenge is valid find the temporary file
- If point 4 succeed, request is successful
Where if normally fails is point 4, for whatever reason. The biggest noob mistake is no DNS record pointing to the source server, and then using something such a Cloudflare also needs special treatment because Cloudflare intercepts DNS.
What about Well Known stuff?
Let’s Encrypt HTTP Challenge likes to write to local disk. In that case this should be there:
location ~ /\.(?!well-known).* {
deny all;
}
Missing index.php
It was a Laravel website, so I also had to add both:
index index.html index.php
and
location / { try_files $uri $uri/ /index.php?$query_string; }
to get the site running.
I believe the location parameter broke the well known location. This error is hard to troubleshoot, see multiple references all with different answers below:
References
- https://www.virtualmin.com/node/58287
- https://www.virtualmin.com/node/56388
- https://laravel.com/docs/deployment#nginx
If you are still having problems with Let’s Encrypt and Virtual, contact us on 27 82 309-6710 to sort out.