Cloudflare Zero Trust & Tunnel (cloudflared)

Overview

Cloudflare Zero Trust Tunnels allow services on our private Oracle Cloud VM to be accessed securely over the public internet without opening any inbound ports on the server’s firewall or exposing the host’s public IP address.


1. The Core Concept: Outbound vs Inbound

To understand why this setup is so safe, compare how traditional web hosting works versus how Cloudflare Tunnels work:

flowchart LR
    subgraph Traditional ["Traditional Inbound Hosting (Vulnerable)"]
        Bot1["Internet Bots / Scanners"] -->|Probes Port 80/443| OpenFW["Open Firewall"]
        OpenFW --> Server1["Server IP Exposed"]
    end

    subgraph TunnelModel ["Cloudflare Zero Trust Tunnel (Our Setup)"]
        Client["User Browser"] -->|HTTPS| CFEdge["Cloudflare Edge"]
        CFEdge <-.->|Outbound Encrypted Pipe| Daemon["cloudflared on VM"]
        Daemon -->|localhost:80| Caddy["Caddy Proxy"]
        FW["Firewall: 100% Closed"]
    end

Why We Use Cloudflare Tunnels:

  1. No Inbound Ports: Oracle Cloud Security Lists allow 0 inbound web ports. Automated port scanners cannot detect any web services running on 144.21.49.153.
  2. Hidden IP Address: Web traffic resolves to Cloudflare’s globally distributed anycast proxy IP addresses (104.21.x.x), not the real server IP.
  3. DDoS & Bot Protection: Cloudflare filters malicious volumetric attacks, automated scrapers, and malicious payloads before traffic ever reaches our server.
  4. Automatic SSL/TLS Certificates: Cloudflare automatically provisions and renews edge SSL certificates for all *.ganeshr.me subdomains.

2. Configuration & Ingress Mapping

All incoming web requests for our subdomains hit Cloudflare’s edge and are forwarded over the tunnel to the VM’s local port 80 (where Caddy is listening):

Public HostnameTunnel DestinationInternal Handler
hq.ganeshr.mehttp://localhost:80Caddy Homepage (:3000)
auth.ganeshr.mehttp://localhost:80Caddy Authelia (:9091)
vault.ganeshr.mehttp://localhost:80Caddy Vaultwarden (:80)
cockpit.ganeshr.mehttp://localhost:80Caddy Cockpit (:9090)
wealth.ganeshr.mehttp://localhost:80Caddy Wealthfolio (:8088)

Serverless Exception: notes.ganeshr.me

Unlike the VM-hosted services above, notes.ganeshr.me does not route through the tunnel to Caddy. Instead, it is hosted directly on Cloudflare Pages and protected at the edge by Cloudflare Zero Trust Access (GitHub OAuth SSO). See 09 - Digital Garden & Serverless Notes Portal for the full architecture.

Why Route All Hostnames to localhost:80?

Instead of having Cloudflare try to manage multiple internal port targets, all traffic is funneled to port 80. Caddy acts as the internal traffic controller, using the incoming HTTP Host header to dispatch requests to the correct Docker container.


3. Host-Level Implementation

On the Oracle Cloud VM, the tunnel runs as a native systemd background service.

Components:

  • Binary: /usr/bin/cloudflared
  • Service: /etc/systemd/system/cloudflared.service
  • Token File: /etc/cloudflared/token
  • Tunnel ID: 5a1b6182-75b5-407b-99ea-ea900458f1a8

Systemd Service Configuration (cloudflared.service):

[Unit]
Description=cloudflared
After=network-online.target
Wants=network-online.target
 
[Service]
TimeoutStartSec=0
Type=notify
ExecStart=/usr/bin/cloudflared --no-autoupdate tunnel run --token-file /etc/cloudflared/token
Restart=on-failure
RestartSec=5s
 
[Install]
WantedBy=multi-user.target

4. Day-to-Day Cheatsheet

Check Tunnel Status

To verify whether the tunnel is actively connected to Cloudflare edge nodes:

sudo systemctl status cloudflared

Look for: Active: active (running) and log lines showing registered connections (e.g. Registered tunnel connection ... protocol=quic).

View Live Tunnel Traffic & Logs

sudo journalctl -u cloudflared -f

Restart the Tunnel

If network changes occur or the connection drops:

sudo systemctl restart cloudflared

5. Beginner Troubleshooting Guide

Symptom / ErrorRoot CauseFix
Error 1033: Argo Tunnel errorThe cloudflared daemon on the VM is not running or the VM is offline.Run sudo systemctl status cloudflared. If stopped, run sudo systemctl restart cloudflared. Check Oracle Console if the VM is running.
Error 502 Bad GatewayThe tunnel is working, but the destination service (localhost:80 / Caddy) is down.Run cd /opt/vaultwarden && sudo docker compose ps. Verify the caddy container is running and healthy.
Error 521 Web Server is DownCaddy refused the connection on port 80.Restart Caddy: sudo docker restart caddy. Check Caddy logs: sudo docker logs caddy.
SSL/TLS Handshake ErrorCloudflare SSL encryption mode mismatch.In Cloudflare Dashboard SSL/TLS, ensure encryption mode is set to Full (or Flexible when terminating at edge).