523 means Cloudflare couldn't even open a TCP connection to your origin — DNS points somewhere dead, the origin is down, or a firewall is dropping Cloudflare's IPs.
The A record Cloudflare proxies to is stale or the server is offline. Test the origin directly: curl -I --resolve your.domain:443:<origin-ip> https://your.domain/.
Cloudflare connects from published IP ranges (https://www.cloudflare.com/ips/). If your origin firewall whitelists nothing or blocks datacenter IPs, Cloudflare can't reach it while you still can.
Cloudflare proxying only connects on specific ports (80, 443, 8080, 8443...). An origin on port 3000 with no reverse proxy = unreachable by design.
curl -vI --resolve your.domain:443:<origin-ip> https://your.domain/ # connects = firewall/DNS issue; fails = origin down
dig +short your.domain @1.1.1.1 # proxied records return Cloudflare IPs; check the A record value in the Cloudflare dashboard instead
# for cf in $(curl -s https://www.cloudflare.com/ips-v4); do ufw allow from $cf to any port 443 proto tcp; done
ss -tlnp | grep -E ':(80|443)\b' # app on 3000? put nginx/caddy in front on 443
523 vs 522: 523 = no TCP connection established at all (routing/firewall/down); 522 = TCP connected but timed out during handshake. Different debug paths. For a true Cloudflare-Tunnel setup, 523s usually mean the tunnel daemon (cloudflared) is down on the origin.
You're likely bypassing the failure — browser cache, or your network reaches the origin while Cloudflare's edge can't (firewall blocking CF ranges). Reproduce with curl --resolve against the origin IP to see what Cloudflare sees.
Temporarily allow Cloudflare's published ranges (they're stable and machine-readable at cloudflare.com/ips). If 523 turns into 200s, the firewall was the story — then tighten to only the ports you proxy.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.