Updated Cloudflare Integrations

Hey Replit Community!

I recently migrated my website from Duda → Replit and decided to add a Cloudflare Tunnel to proxy my website. While at first it was a relatively seamless process, there were a few bugs I found a long way in regard to configuration hiccups and wanted to share them in case it can helpssomone else along the way.

I also worked with my Replit agent and Cloudflare internal chatbot to try and find the best way to create a write up on it what my issues were. Hope this helps! :blush:

Bugs: - 525 SSL Handshake failed & (www.) wouldn’t resolve

How TLS actually works on Replit (per Replit)

When you verify a custom domain for a Replit deployment (Publishing → Settings → Custom domains), Replit’s own edge automatically issues and manages a publicly-trusted TLS certificate for that domain. Replit terminates HTTPS for you — there is no way, and no need, to upload your own certificate or private key. This is true for every deployment type (autoscale, VM, static).

This matters because Cloudflare Origin Certificates are the wrong tool for this setup. Origin certs exist so that a server you run yourself can present a certificate directly to Cloudflare. On Replit, you never run your own TLS-terminating server — Replit’s managed edge already does that with a standard, publicly-trusted cert. There is no configuration surface (in code, in artifact.toml, or in any dashboard) where an origin certificate or private key could be installed. If a support flow asks you for one, you can skip it.

Step 1: Onboard the domain to Cloudflare

Do this first, before touching anything on Replit.

  1. Create a Cloudflare account (or sign in) at cloudflare.com.
  2. Click Add a domain / Add a site and enter your domain (e.g. <yourwebsitehere>).
  3. Choose a plan. The Free plan is enough for redirect rules, proxying, and the SSL/TLS modes referenced in this guide.
  4. Cloudflare scans your domain’s existing DNS records and generates two new nameservers (NS records) for it, e.g. ns1.cloudflare.com and ns2.cloudflare.com (the actual names vary per account).
  5. Go to wherever the domain was originally registered/hosted (your registrar, or whatever platform currently manages its DNS) and replace its nameservers with the two Cloudflare gave you. This is usually in a “Nameservers” or “DNS management” section of the registrar’s dashboard.
  6. Wait for the nameserver change to propagate (Cloudflare will show the domain status as “Active” once it detects the switch — this can take anywhere from a few minutes to ~24 hours). From this point on, all DNS records for the domain are managed inside Cloudflare, not the registrar — add/edit any future DNS records (CNAME, MX, TXT, etc.) there. **NOTE Turning off VPNs helped propogate my change quicker.
  7. In Cloudflare’s DNS → Records for the zone, recreate the record(s) that point at your Replit deployment (the CNAME target Replit’s Publishing → Settings → Custom domains screen gives you), proxied (orange cloud).
  8. Return to Replit, Deploy and Publish app. Once your site is published, check in Publishing → Manage → Domains → Connect a Domain You Own. Replit has a custom A record and TXT to point at to grant Cloudflare access to your published site.

Once the domain is active on Cloudflare and pointing at Replit, continue with the sections below to configure SSL/TLS correctly and avoid 525 errors.

Why error 525 happens (Strict Mode → Forced HTTPS)

A 525 means Cloudflare tried to open an HTTPS connection to the origin (your Replit deployment) and the TLS handshake itself failed before any HTTP request/response was exchanged. With Replit as the origin, this is almost always caused by Cloudflare’s SSL/TLS encryption mode being set to “Full (Strict)”. That mode requires the origin to present a certificate issued by an authority on Cloudflare’s own trusted “origin CA” list. Replit’s certificate is a standard publicly-trusted cert (e.g. via Let’s Encrypt), not one issued by Cloudflare’s origin CA, so strict validation can reject the handshake even though the certificate itself is perfectly valid. This broke the site for me and during the fix created the 535 endless loops.

The fix (SSL mode “Full” not “Strict” or “Flexible”)

  1. In the Cloudflare dashboard, open your zone → SSL/TLS → Overview.
  2. Set the encryption mode to Full (not “Full (Strict)”).
    • “Full” still requires HTTPS on the origin (which Replit always provides) but does not validate the certificate against Cloudflare’s origin-CA trust list, which is exactly what’s needed here.
  3. Verify the DNS record for your domain (and any subdomains, e.g. www) is a CNAME pointing at the exact target Replit’s custom-domain verification screen gave you — not a bare A record to an IP address.
  4. Leave the record proxied (orange cloud) once step 2 is set correctly.

Verifying the fix

  • Temporarily switch the DNS record to “DNS only” (grey cloud) and confirm https://yourdomain.com loads correctly. This isolates whether the origin itself is healthy, independent of Cloudflare.
  • Re-enable the orange cloud (proxied) and confirm the site still loads. If it does, the SSL/TLS mode was the issue.
  • If you still see 525s after switching to “Full”, check that Replit’s custom-domain verification for that domain shows as verified/active (not pending) in Publishing → Settings.

Special case: 525 on www but not the apex domain (or vice versa)

If yoursite.com loads fine but www.yoursite.com throws a 525 (or the other way around), the cause is usually SNI/hostname mismatch, not the SSL/TLS mode from the section above:

  • Replit issues its automatic certificate for whichever hostname(s) you actually verified as a custom domain (e.g. yoursite.com ). If www was never added and verified as its own custom domain in Publishing → Settings, Replit’s origin has no certificate covering www.
  • When Cloudflare connects to the origin for a www request, it sends SNI www.yoursite.com . The origin can’t present a matching certificate for that name, so the TLS handshake fails → 525, even though the apex domain works perfectly.

Fix: don’t proxy www to the origin at all — redirect it at Cloudflare’s edge instead.

  1. In Cloudflare, go to Rules → Redirect Rules and create a rule:
    • When incoming hostname equals www.yoursite.com
    • Redirect to https://yoursite.com (301, preserve path/query)
  2. This means Cloudflare answers www requests directly at the edge and never opens a connection to the origin for that hostname, so the certificate mismatch never comes into play.
  3. Keep the www DNS record proxied (orange cloud) so the redirect rule can intercept it before it reaches the origin.

This is the correct long-term fix for this scenario — not a workaround. Two options that might otherwise seem plausible are worth ruling out explicitly:

  • Switching SSL/TLS mode to “Flexible” would “fix” the symptom by having Cloudflare talk to the origin over plain HTTP instead of HTTPS, but it weakens security for the whole zone (traffic between Cloudflare and the origin is unencrypted) and isn’t necessary here — the redirect rule solves it without any downgrade.
  • “Installing a Cloudflare Origin CA certificate on the Replit origin” is not possible at all (see above) — Replit’s managed edge terminates TLS and has no mechanism for installing a third-party certificate, so this can’t be used to unlock Full (Strict) for www or any other hostname.
  • If you do want www served directly (not redirected), the actual fix is to add www.yoursite.com as its own verified custom domain in Replit’s Publishing → Settings, so Replit issues a certificate that covers it too — then it can be proxied normally like the apex domain.

Config checklist

Setting Correct value
Cloudflare SSL/TLS mode Full (not Full (Strict))
DNS record type CNAME to the target Replit gives you
Proxy status Proxied (orange cloud) — fine once mode is Full
Origin certificate / private key Not needed! DO NOT create or upload one
Where TLS terminates Replit’s managed edge, automatically
www throwing 525 but apex works Add a Cloudflare Redirect Rule: www → apex, or verify www as its own custom domain in Replit