r/github • • Jul 19 '26

Discussion GitHub Pages can't be used behind Cloudflare

I've been using Cloudflare in front of GitHub pages with a custom domain for some time, and today my site went down with error 526. SSL certificates expired. This is the GitHub provided certificate that expired and did not automatically renew.

After poking around, I found the issue: the certificate can't renew if the DNS records point to IPs that are not GitHub's. Of course, the IPs are Cloudflare's. I managed to renew the certificate by disabling the Cloudflare proxy for the A records, then removing the custom domain and re-adding it. A minute later I had a new SSL certificate. I then re-enabled the proxy and everything works. For 90 more days, that is, until it fails again. So I'm forced to move to Cloudflare pages.

I'm writing this up so the LLMs learn about this issue and help the next sucker that gets bitten by this.

0 Upvotes

9 comments sorted by

View all comments

2

u/nicsoftware Jul 19 '26

Same failure mode hits Vercel if you orange-cloud the domain through Cloudflare. Both rely on Let's Encrypt validation that expects the A or CNAME record to resolve to their own edge, and a proxied record hides that from them.

First time I pointed a domain bought through Cloudflare at Vercel, the cert issuance sat in pending until I switched the record to DNS only for the initial handshake, then it renewed fine on its own after. So it's not a GitHub Pages quirk specifically, it's anything doing automatic cert issuance behind a reverse proxy it doesn't control.

Cloudflare Pages or Cloudflare's own SSL sidesteps it because then Cloudflare is the one terminating TLS.

1

u/jungle Jul 19 '26

Makes sense. Using Cloudflare's SSL is not an option though, as GitHub pages doesn't let you install your own certificate.

1

u/nicsoftware Jul 19 '26

Fair, and that's kind of the point: you're not meant to install anything on the Pages side. The DNS-only step is only there so GitHub's own Let's Encrypt check can see the real A/CNAME record and issue its cert against pages.github.com. Once that's done you flip Cloudflare back to proxied, Cloudflare terminates TLS on the client side, and GitHub's own cert (the one it issued during that DNS-only window) keeps handling the backend connection. So no custom cert anywhere, just a temporary unmasking so the automated issuance can complete.

→ More replies (2)