This isn't a help request, and obviously it's not directly to do with LetsEncrypt - but it may be relevant for anyone who (like me!) sets up a proxied domain on Cloudflare, hosted on Github Pages (or a similar platform that uses Letsencrypt certificates). All is well at first until a few months later, when you get a TLS/SSL error forcing you to turn off the Cloudflare proxy.
This is becuase the Cloudflare proxy will re-write the Letsencrypt port 80 request to the .well-known URL of your site to port 443, so renewal can't happen.
The solution involves using two Cloudflare page rules to allow the necessary port 80 request, but keep all other requests over TLS/SSL (If you're on the Cloudflare free tier, you get a maximum of three page rules).
Note that at the time of writing I've implemented this (and successfully tested it as per the guide), but won't know if it's definitely worked until the the actual renewal in a couple of months time.
When Cloudflare proxies a domain, you can control the security policy of the upstream origin. There is no need to have a publicly trusted LetsEncrypt certificate on the origin (unless as a backup for disabling the proxy). Cloudflare can use a self-signed cert, expired public cert, and many options in between to handle that connection. They will even provide you with “long term” certs to install on the origin. They will then obtain their own certs from public cas to encrypt the connection from their network to your visitors.
Your fix gets the job done, but this setup is usually not needed.
That alone won't prevent renewal. A redirect to HTTPS on port 443 will be followed by the Let's Encrypt auth server. As long as your server is prepared to handle it arriving on port 443 it will work. Maybe that is something unique to github pages (idk) but it is not a general restriction. See the LE redirect support here: Challenge Types - Let's Encrypt
Aside from that, Page Rules are one option but this is another from a frequent contributor at the Cloudflare Community. Actually, MVP there 2023-25
I don't know what it is about the Cloudflare setting for Always Use HTTPS that breaks the ACME HTTP-01 challenge, but it isn't just limited to git powered static histong. It caused problems for me with Apache sites on self-managed VPS that were using certbot webroot at the time.
Once I had working configuration options, my interest in why dropped below the threshold required to prompt further investigation. Maybe it will rise up my list and reach an actionable state one day. Until then, I will keep using my preferred exemptions.
I use mod_md with Apache now. I prefer TLS-ALPN-01, but that doesn't work with sites behind the Cloudflare proxy for hopefully obvious reasons.
Maybe because the server isn't expecting to see it on port 443? Very old versions of Certbot's nginx plugin, for example, only setup port 80 for the challenge. Only starting about 3 years ago the certbot --nginx sets up both port 80 and port 443 for this specific situation. (see: certbot/certbot/CHANGELOG.md at main · certbot/certbot · GitHub). Not sure if, or when, the --apache plugin did that.
For Certbot --webroot you'd have to make sure the webroot-path matched your port 443 virtual host if you (or Cloudflare or anyone) redirected HTTP there.
There really isn't anything unusual about Cloudflare redirecting compared to all the other cases of people we see redirecting their HTTP Challenge.
When going to the site's URL, we got a CloudFlare error page saying that while all was well at their end, there was a problem with the connection from their systems to the origin, which related to the origin's cert. Disabling the CF proxy (and perhaps re-issuing the certificate with GitHub - they were a bit vage on that but there was a message about HTTPS in the GitHub pages config) cured it.
And as I say, the tests I've done indicate that the proxy should now work, but I won't know for sure until the next renewal.
Might it be becuase CloudFlare's "always use HTTPS" setting prevents a redirect happening? The solution involves turning that off and replacing it with the selective page rule to let the acme port 80 request in maybe. But I'm just guessing.
I think setting Always HTTPS along with certain Encryption Modes means the Cloudflare CDN sends the HTTP Challenge to your Origin Server as HTTPS. But, if you haven't yet configured your Origin to handle HTTPS (port 443) it will fail.
Once you get the cert and setup your Origin it should be fine. It would also be fine if you adjust those settings to not use HTTPS to your Origin until you get your first cert. Or, use "snakeoil" certs on your Origin for HTTPS and then replace those with the Let's Encrypt cert.
I think your Page Rule or linkp's alternate suggestion "solve" this by making sure the HTTP Challenge gets sent to your Origin as HTTP even for the first request.
Another option is the Cloudflare Origin CA cert which can be a good choice. If not as a permanent solution to work as the initial cert to allow your Origin to handle HTTPS before getting a public CA cert.
Not sure I follow. I had no control over the type or deployment of the GitHub origin certificate, and HTTPS is compulsory I think. But in any case I set up and checked the Pages site was working OK (over HTTPS), did the necessary DNS bits to auth the custom domain for it, which in my case also included the CloudFlare proxy for it.
That setup worked fine for three months until a renewal happend (I assume) and it broke. Various discussions on other forums described the same problem BTW, which eventually led me to the guide I posted.
Is there a particular reason why you are fronting Github Pages on Cloudflare?
Github can enforce HTTPS and will handle all the CDN requirements on their end. Their unofficial position on this setup seems to be that you should not proxy through Cloudflare; from what I've read, Cloudflare seems to believe you should either not proxy through them, or modify your SSL settings to Origin into the "flexible" mode.
What you're doing works, but neither provider seems interested in supporting this type of integration between the two.
[At the risk of forking the thread] to use the various functions CloudFlare provides that GH Pages doesn't. In my case was so that we can have multiple admin accounts to manage the zones, billing etc. because we're also using CF for domain registration, but also for things like stats, DDoS protection and other things.
The reason why I posted here was becuase I (naively) thought the default condition of having the CF proxy in place - which worked just fine at first - was going to work
I'm not sure that's related. Here's an example of someone having the same problem (CF -> GH works at first, but then breaks later on).
The explanation is that initially, GitHub Pages uses a cert obtained using a CNAME that resolved to its own IP. But on renewal, the IP that comes back from the DNS query that GitHub makes belongs to Cloudflare. So GitHub can’t successfully renew, hence the need to prevent the .well-known URL from being served via the CloudFlare 443 proxy I think?
What you describe is not possible. A hostname is either proxied or not. A path cannot be selectively "unproxied". Let's Encrypt certificates renew every day using Cloudflare proxied connections.
Not possible using the CF proxy settings, no. But as per the solution I linked to in my original post, I think using a CF page rule to turn off SSL for the URL being challenged (via the CNAME to the GitHub IP) but having all other URLs under SSL, effectively does that.
But again, I intend to wait until the next origin renewal before declaring it a success.
No, it doesn't do that at all. Cloudflare settings, including Page Rules, are applied by the proxy. If the requst is not proxied, the rules cannot be applied. The requests are proxied, just over HTTP instead of HTTPS. That is the important part. Anyway, your renewal should work fine. All of my Cloudflare proxied sites use similar setttings.
Incidentally, you said your interest in why the problem occurs wasn't enough to prompt further investigation. But do you think GitHub (or whatever origin platform that's using LE) gets a successful challenge resolving to its own IP as given by the DNS CNAME (that is, username.github.io), and becuase that host's certificate is provisioned first, the setup initially works OK? So the origin's cert renewal later fails because CF proxy will present username.github.io as resolving to a CF IP from then on?
There are two problems here, one that can be fixed, the other that cannot.
If the SaaS provider expects HTTP-01 validation, they sometimes set up challenge under http:// only. In that situation setting up a Page Rule (or even better: Configuration Rule, you get 10 of these on Free plan), e.g.:
if:
URI Path, starts with, /.well-known/acme-challenge/
then:
SSL = Flexible (it'll forward HTTPS request to HTTP origin)
If the SaaS provider actively checks for DNS record (e.g. Google Sites), and likely GitHub Pages, too, then there's nothing for you to do. You just need to use CNAME/A with proxy off, otherwise these providers will simply refuse to issue the certificate.
I'm afraid we might deal with situation #2 here.
You could disable proxying once in a while to allow GitHub to satisfy the "my DNS record only" need, but it's not going to be sustainable, unfortunately. Alternatively, set GitHub Pages to disable "Enforce HTTPS", and set Cloudflare for SSL = Flexible. None of these are ideal.
Ideal solution would be for SaaS provider to simply drop the "my DNS record only" requirement, and simply attempt HTTP-01 (through HTTP and HTTPS) unconditionally. I wouldn't hold my breath waiting for it, though.
I just reminded myself of little-known fact Re: Cloudflare SSL mode.
In "Full strict" mode, Cloudflare Edge validates origin's SSL cert to be issued by well-known CAs, but it also checks for either hostname in CNAME record (source or target), e.g. mypage.example.com CNAME username.github.io
"Full strict" mode will consider cert valid if either mypage.example.com or username.github.io is in SANs. Given GitHub Pages deploy *.github.io as their default certificate, it might work without need to set SSL = Flexible. Depends on whether Pages allow HTTPS traffic without cert issued (my quick try indicates it does).
Please don't ever use that. It has always been an insecure hack and makes it impossible for your visitors to ever trust that your site is actually secured.
It's quite clearly documented right next to the setting, but no one really reads anymore.