Let’s Encrypt HTTP challenge and Cloudflare

This is a super quick, super short post - uh, I haven’t written anything in ages!

I have been using Cloudflare for my sites/apps for a while now; I love how easily and quickly you can have a website with CDN and security features like DDoS protection (even with the free plan), plus the DNS management is also better than what others offer. I also use Let’s Encrypt for free TLS certificates; you can enable TLS with Cloudflare as well, but that would secure only the connection between Cloudflare and the end users. So it’s better to enable HTTPS on the origin server too so to also secure the connection between the origin server and Cloudflare.

In order to issue a certificate for a domain, Let’s Encrypt requires that the ownership of the domain be verified first. There are a few methods to do this, and I usually prefer using the DNS-01 challenge method (using Cloudflare) for domains under my control. This isn’t possible however if I don’t have access to the DNS configuration (for example with users’ custom domains in a SaaS app), so in such cases I use the HTTP-01 challenge method instead. See the link above for the details, in short this challenge requires that a URL in the format

http://<YOUR_DOMAIN>/.well-known/acme-challenge/<TOKEN>.

be accessible from the outside world - note that it’s HTTP, not HTTPS since it’s assumed HTTPS/TLS is not enabled yet (well, that’s why we want to request a certificate). If that address is accessible, it means that you own the domain because otherwise you wouldn’t be able to configure the DNS for the domain so that it points to the server which is requesting the certificate. When the verification succeeds, Let’s Encrypt can successfully issue the certificate.

If before doing this you were already using Cloudflare, chances are that you may have enforced HTTPS on the website with Cloudflare itself. If that’s the case, the Let’s Encrypt HTTP challenge will fail and the certificate won’t be issued, because any visit to the challenge URL will be automatically redirected to the HTTPS equivalent.

The fix is actually pretty easy. Head over to the Cloudflare control panel and under the Page Rules tab, add a rule as follows with your domain name:

*yourdomain.com/.well-known/acme-challenge/*

Before saving the page rule, 1) set both SSL and Automatic HTTPS Rewrites to Off, 2) make sure this is set as the first rule - Cloudflare will stop processing rules at the first match. Here’s a screenshot:

Cloudflare page rule to enable Let's Encrypt HTTP challenge

Finally, ensure SSL is set to Full under Crypto, otherwise you will see some kind of redirect loop:

Cloudflare SSL Full

Give it a a minute for the changes to take effect, then have your ACME client on the server try requesting the certificate. It should work just fine. Hope this helps! :)