Enviera

REPLIT + CLOUDFLARE

Replit custom domain ERR_CONNECTION_CLOSED or SSL_ERROR_SYSCALL: no certificate on www, expired on the apex

What you see

  • Chrome shows ERR_CONNECTION_CLOSED on your custom domain, usually on www.
  • curl -I https://www.yourdomain.com fails with SSL_ERROR_SYSCALL.
  • The *.replit.app address of the same deployment still works.
  • Your DNS is on Cloudflare. The apex (yourdomain.com) may still load, so it looks like only www is broken. It may not be.

What we saw

In October 2026 we fixed this for a US marketplace site running on Replit Deployments, with DNS on Cloudflare in SSL mode “Full”. www served no certificate at all, so browsers closed the connection. The apex's Let's Encrypt certificate had also expired. Visitors never saw the expiry, because Cloudflare in “Full” mode accepts an expired origin certificate and keeps serving visitors.

Why it happens

Our incident record doesn't say which of these broke for us. These are the conditions Replit's docs set for issuing and renewing certificates, so rule out each one.

  • Replit renews certificates through DNS. Replit issues a separate Let's Encrypt certificate for each domain and subdomain you connect, and renews it through DNS validation. Two things have to stay true for as long as the domain is in use.
  • The records must be DNS only. Replit's docs say it can't renew certificates for Cloudflare-proxied records (orange cloud) and ask you to set them to DNS only (grey cloud).
  • The replit-verify TXT record must stay. Replit's docs say to treat it as permanent alongside your A record. If you remove or change it, the next renewal fails and the domain ends up serving an expired certificate.
  • If www isn't linked as its own domain, it has no certificate on Replit's side. Linking the apex doesn't serve www. It needs its own entry in the Domains tab and its own DNS records.
  • Cloudflare “Full” hides the expiry. In “Full” mode Cloudflare doesn't validate the origin certificate in any way; it can be expired or self-signed. So a proxied apex keeps working for visitors while the certificate behind it has expired.
  • Let's Encrypt certificates last 90 days, so a renewal that quietly stops breaks the site within three months.

Expired certificates on Replit custom domains have been reported on the Replit forum since August 2025, and in the threads we read no Replit staff member answered. Users there reported the same kind of fix: disconnecting and reconnecting the domain (some removed and re-added it). Disconnecting and reconnecting is what worked for us.

How to fix it

  1. Check what each hostname actually serves. Run the free checker on your domain (it checks the apex and www). For a name that is proxied through Cloudflare, the checker can't see the certificate behind the proxy, so check the origin directly, using the A record value Replit gave you:
    openssl s_client -connect <Replit A record IP>:443 -servername yourdomain.com </dev/null | openssl x509 -noout -enddate
    -servername sends your hostname to Replit's server, so you get the certificate for your domain. -enddate prints its expiry date. Repeat with www.yourdomain.com. If no certificate comes back, that hostname has none.
  2. Set the Replit records in Cloudflare to DNS only. In Cloudflare DNS, switch the A record for the apex (and the record for www, if Replit serves it) from Proxied to DNS only. This takes Cloudflare's caching and protection, including WAF rules and DDoS protection, off that hostname, and your Replit IP becomes visible to anyone who looks up the record. If you need those, see When to get help.
  3. Check the replit-verify TXT record for each hostname. It must match what the Replit Domains tab shows. Put it back if it is missing.
  4. Make sure www is linked as its own domain in the Replit Domains tab, with its own records. If you only want www to redirect to the apex, see the prevention list below.
  5. Disconnect and reconnect the domain in Replit's Domains tab, once. This is what got us a new certificate. Replit requests a new certificate on each reconnect, so its docs advise against repeated retries. DNS changes can take up to 48 hours to reach Replit. If the domain shows Failed, Replit stopped checking (it checks for about 6 hours); fix the DNS first, then remove and re-add the domain, as Replit's docs say.
  6. Check again. Run the checker or the openssl command on both names. You should see a new certificate with an expiry about 90 days out.

How to stop it happening again

  • Watch the certificate at the origin, not through Cloudflare. Alert when fewer than 20 days are left. A healthy setup renews well before that; Let's Encrypt recommends renewing 90-day certificates every 60 days.
  • Keep Replit-served records DNS only, with a permanent replit-verify TXT on every hostname Replit serves.
  • Don't host a name on Replit only to redirect it. If one name only redirects (for example the apex to www), remove it from Replit's Domains tab, keep its Cloudflare record Proxied (orange cloud), and redirect it with a Cloudflare Redirect Rule. Cloudflare redirects only run on proxied records, so on a DNS-only record the rule never fires. That leaves one fewer certificate for Replit to renew.
  • Put a check in your calendar halfway through each certificate's life.
  • If you need Cloudflare's proxy in front of the app, plan for it: proxy to your *.replit.app address through a Cloudflare Worker, or host the app somewhere that supports the proxy.

When to get help

  • You reconnected once, waited, and the domain still shows Failed or has no certificate.
  • You need the Cloudflare proxy on (WAF, caching) and can't drop it.
  • The outage has already cost you traffic and you want the setup checked end to end.

We rescue and finish apps built on Replit, Lovable and Bolt: see Fix my Replit app. Seeing Error 525: SSL handshake failed from Cloudflare instead? That is a different failure with a different fix: Replit 525 behind Cloudflare.

Check your custom domain's certificate now (free)

Enter your domain and we check the apex and www: whether each has a certificate, when it expires (for names not behind the Cloudflare proxy), whether replit-verify is there and whether the Cloudflare proxy is on.

Check my domain

Sources

  1. Replit Docs, "Custom domains"
  2. Cloudflare, "Full" SSL/TLS mode
  3. Cloudflare, "Proxy status"
  4. Cloudflare, "Redirects"
  5. Let's Encrypt, "FAQ"
  6. Replit Community Forum, "SSL certificate expired for custom domain" (user posts, 2025-08-28 to 2026-02-08, not Replit staff)
  7. Replit Community Forum, "SSL certificate not renewing automatically (custom domain)" (user post, 2026-02-11, not Replit staff)
  8. OpenSSL 3.0 manual, openssl-s_client
  9. OpenSSL 3.0 manual, openssl-x509