← Guides

Origin vs tunnel: reading 502 and 530

~5 min read · 2026-08-11 · Homelab / Cloudflare Tunnel

When a public hostname returns 502 Bad Gateway or a Cloudflare error page (often 530, 1033, or 1016), the instinct is “the app is down.” Half the time the app is fine on the LAN — the tunnel connector simply cannot reach it, or DNS never pointed at the tunnel. If you only check the browser, you will restart the wrong process for an hour.

This guide gives you a two-probe method that separates origin problems from edge/tunnel problems, explains the remote-connector trap that causes most homelab 502s, and shows how to automate the check so you stop guessing at 2 a.m.

What the error usually means

SymptomOften meansFirst place to look
Browser 502 via HTTPS Tunnel reached Cloudflare, but origin fetch failed Service URL in tunnel config, bind address, firewall
Cloudflare 530 / connector errors Tunnel not connected or mis-mapped cloudflared status, hostname routes
DNS fails / NXDOMAIN Hostname not created or wrong zone DNS records, proxy orange-cloud
LAN works, public fails Classic tunnel path problem This guide’s two-probe method
LAN fails too App/process/bind problem Process manager, port, app logs

The remote-connector trap

Homelabs often run cloudflared on a different machine than the app (a small always-on box as the connector, apps on a workstation or separate VM). That architecture is fine — until the tunnel service URL is set to:

http://127.0.0.1:8100

127.0.0.1 means “this machine.” On the connector host, that is the connector — not your app. Cloudflare gets a connection, tries the origin, and returns 502 because nothing is listening on that port on the connector.

Fix pattern: bind the app to 0.0.0.0 (or the LAN interface) and point the tunnel at the app’s LAN IP, e.g. http://10.2.13.159:8100, not localhost.

Also check host firewalls: the connector must be allowed to TCP-connect to that LAN IP and port. “Ping works” does not prove the app port is open.

The two-probe method

Always run both probes from a machine that can reach the LAN (or from the app host itself for probe A).

Probe A — origin (LAN)

curl -sS -o /dev/null -w "%{http_code}\n" --connect-timeout 3 \
  http://10.x.x.x:PORT/

Probe B — public edge

curl -sS -o /dev/null -w "%{http_code}\n" --connect-timeout 10 \
  https://your.hostname.example/

How to read the pair

LANPublicConclusion
FailFailFix the origin first (process, bind, port)
OK502Tunnel service URL / path / connector reachability
OK530 / connector errorsTunnel not running or hostname not routed
OKDNS failCreate/fix DNS for the hostname
OKOKYou are done — look at caching/auth if content is wrong

Checklist when LAN is OK but public is 502

  1. Confirm cloudflared is connected (logs show a registered connection).
  2. Open the published hostname route: service URL must be the LAN origin, not 127.0.0.1 on the wrong box.
  3. From the connector host, curl the same LAN URL the tunnel uses.
  4. Watch for path mismatches (/ vs app under a subpath).
  5. If the origin only binds 127.0.0.1, remote connectors can never reach it — rebind to 0.0.0.0.
  6. After fixing, re-run both probes before declaring victory in the browser (CDN can cache error pages briefly).

Stale processes: the silent 502

Another common pattern: the app was started once under nohup or a manual shell, the host rebooted or the process died, and the tunnel still exists. Public DNS resolves, Cloudflare is healthy, origin is empty — classic 502. Use a process supervisor (systemd, Docker restart policy) or a healthcheck that restarts dead listeners. A tunnel is not a process manager for your app.

Check both sides in one step

If you run this dance often, automate it. Two curls work. For inventory-style checks (many services), the free OriginReach CLI probes origin and public URLs and prints a verdict such as ok, origin_down, edge_break, or dns_fail.

originreach check \
  --origin http://192.168.1.50:8080/ \
  --public https://app.example.com/

# Many services at once (JSON inventory):
originreach check -i inventory.json --exit-code

Use --exit-code in CI or cron so a broken tunnel or dead origin fails the job instead of waiting for a customer email.

What not to do

Related: Env drift checklist · OriginReach free download · Independent notes from Tactical Data Concepts; not affiliated with Cloudflare.