Cloudflare Tunnel: Not Working — Fix

The Problem

Your Cloudflare Tunnel is set up but services aren’t reachable. You might see: 502 Bad Gateway errors, the tunnel shows as “Inactive” in the Cloudflare dashboard, DNS records exist but the site won’t load, or connections hang and eventually time out.

The Cause

Cloudflare Tunnel issues typically stem from one of four areas: the cloudflared connector not running or failing to authenticate, incorrect ingress rules pointing to the wrong local address, DNS records not properly routing to the tunnel, or the local service not listening on the address cloudflared expects.

The Fix

Method 1: Check Tunnel Status

Verify the tunnel connector is running and connected:

# If running as a system service
sudo systemctl status cloudflared
sudo journalctl -u cloudflared -f

# If running in Docker
docker logs cloudflared

# Check tunnel status via API
cloudflared tunnel info <tunnel-name>

Look for:

  • Registered connectors — should show at least 1 active connection
  • ERR lines — authentication failures, certificate issues
  • connection reset by peer — network issue between your server and Cloudflare

Common fix: If the tunnel shows as “Inactive” in the dashboard but cloudflared is running, the tunnel token or credentials file may be expired. Regenerate:

# For token-based tunnels (recommended)
# Get a new token from Cloudflare dashboard: Zero Trust → Networks → Tunnels → Configure
docker restart cloudflared

# For credentials-file tunnels
cloudflared tunnel delete <tunnel-name>
cloudflared tunnel create <tunnel-name>
# Update the credentials-file path in config.yml

Method 2: Fix 502 Bad Gateway

A 502 error means cloudflared reached Cloudflare but can’t reach your local service.

Check: Is the service actually running on the address and port specified in your ingress rule?

# If your ingress says "service: http://localhost:8080"
curl -I http://localhost:8080

# If your ingress says "service: http://nextcloud:8080" (Docker)
docker exec cloudflared curl -I http://nextcloud:8080

Docker networking fix: If cloudflared runs in Docker and your services are also in Docker, they need to be on the same Docker network. Using localhost won’t work — use the container name:

services:
  cloudflared:
    image: cloudflare/cloudflared:2024.12.2
    restart: unless-stopped
    command: tunnel run
    environment:
      TUNNEL_TOKEN: ${CLOUDFLARE_TUNNEL_TOKEN}
    networks:
      - tunnel

  nextcloud:
    image: nextcloud:33.0.0
    restart: unless-stopped
    networks:
      - tunnel

networks:
  tunnel:

In the tunnel config, use http://nextcloud:80 not http://localhost:80.

Method 3: Fix DNS Routing

If the domain resolves but traffic doesn’t reach the tunnel:

  1. Check the DNS record in Cloudflare dashboard → DNS → Records
  2. The record should be a CNAME pointing to <tunnel-id>.cfargotunnel.com with the orange cloud (proxied) enabled
  3. If the record doesn’t exist, add it:
cloudflared tunnel route dns <tunnel-name> subdomain.yourdomain.com

Multiple subdomains: Each hostname in your ingress rules needs its own DNS CNAME record.

Method 4: Fix HTTPS/SSL Issues

If the service uses HTTPS internally (e.g., port 443 with a self-signed cert), cloudflared will fail to connect by default:

ingress:
  - hostname: service.yourdomain.com
    service: https://localhost:8443
    originRequest:
      noTLSVerify: true  # Accept self-signed certs from your service

For services that require HTTP/2:

ingress:
  - hostname: service.yourdomain.com
    service: https://localhost:8443
    originRequest:
      http2Origin: true

Method 5: Fix WebSocket Services

Some apps (Home Assistant, Homarr, code-server) require WebSocket connections. cloudflared supports WebSockets by default, but you may need to ensure your service URL is correct:

ingress:
  - hostname: ha.yourdomain.com
    service: http://homeassistant:8123

If WebSocket connections drop, check your Cloudflare dashboard: SSL/TLS → Edge Certificates → ensure “Always Use HTTPS” isn’t causing redirect loops.

Prevention

  • Pin your cloudflared version — don’t use :latest. The tunnel protocol can change between versions.
  • Use token-based tunnels (Cloudflare dashboard-managed) instead of credentials-file tunnels — easier to rotate and manage.
  • Monitor tunnel health from the Cloudflare Zero Trust dashboard — set up notifications for tunnel disconnections.
  • Use a catch-all ingress rule at the bottom of your config to return a clear error instead of a generic 502:
ingress:
  - hostname: app1.yourdomain.com
    service: http://localhost:8080
  - service: http_status:404  # Required catch-all

Comments