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:
- 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. - Hidden IP Address: Web traffic resolves to Cloudflare’s globally distributed anycast proxy IP addresses (
104.21.x.x), not the real server IP. - DDoS & Bot Protection: Cloudflare filters malicious volumetric attacks, automated scrapers, and malicious payloads before traffic ever reaches our server.
- Automatic SSL/TLS Certificates: Cloudflare automatically provisions and renews edge SSL certificates for all
*.ganeshr.mesubdomains.
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 Hostname | Tunnel Destination | Internal Handler |
|---|---|---|
hq.ganeshr.me | http://localhost:80 | Caddy → Homepage (:3000) |
auth.ganeshr.me | http://localhost:80 | Caddy → Authelia (:9091) |
vault.ganeshr.me | http://localhost:80 | Caddy → Vaultwarden (:80) |
cockpit.ganeshr.me | http://localhost:80 | Caddy → Cockpit (:9090) |
wealth.ganeshr.me | http://localhost:80 | Caddy → Wealthfolio (:8088) |
Serverless Exception:
notes.ganeshr.meUnlike the VM-hosted services above,
notes.ganeshr.medoes 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 HTTPHostheader 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.target4. Day-to-Day Cheatsheet
Check Tunnel Status
To verify whether the tunnel is actively connected to Cloudflare edge nodes:
sudo systemctl status cloudflaredLook 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 -fRestart the Tunnel
If network changes occur or the connection drops:
sudo systemctl restart cloudflared5. Beginner Troubleshooting Guide
| Symptom / Error | Root Cause | Fix |
|---|---|---|
| Error 1033: Argo Tunnel error | The 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 Gateway | The 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 Down | Caddy refused the connection on port 80. | Restart Caddy: sudo docker restart caddy. Check Caddy logs: sudo docker logs caddy. |
| SSL/TLS Handshake Error | Cloudflare SSL encryption mode mismatch. | In Cloudflare Dashboard → SSL/TLS, ensure encryption mode is set to Full (or Flexible when terminating at edge). |
6. Next Steps & Related Links
- 00 - Homelab Overview & Architecture — Master system architecture and index.
- 02 - Caddy Reverse Proxy & Routing — How Caddy handles the traffic delivered by this tunnel.