A secure outbound connector from on-premise or private network systems to Cloudflare's edge. Expose internal HTTP services, SSH, RDP, or databases without opening inbound firewall ports or managing VPNs.
Cloudflare Tunnel (formerly Argo Tunnel) runs a lightweight daemon (cloudflared) on your server. The daemon opens outbound connections to Cloudflare's nearest PoPs — no inbound ports needed. Cloudflare then routes traffic from the internet (or from Workers via service bindings) to your internal service through that tunnel.
This is the answer to "how does my Worker talk to my on-premise ERP, database, or legacy API without exposing it to the internet?" The tunnel is encrypted, authenticated, and managed via the Cloudflare dashboard or API.
For South African operations, this is particularly relevant: many enterprise clients have on-premise Sage X3 or SAP instances behind corporate firewalls. A tunnel lets a Worker proxy requests to these systems without a VPN, DMZ, or public IP.
Create a tunnel via the dashboard or CLI. Configure which internal services to expose via a config file.
# Create tunnel cloudflared tunnel create erp-connector # config.yml tunnel: abc-123-def credentials-file: /etc/cloudflared/abc-123-def.json ingress: - hostname: erp.company.com service: http://localhost:8080 - hostname: db-admin.company.com service: http://localhost:5432 - service: http_status:404
Run cloudflared as a systemd service. It maintains persistent outbound connections to Cloudflare and routes incoming requests to your local services.
# Install and run as service cloudflared service install systemctl start cloudflared # Or run directly cloudflared tunnel run erp-connector # Quick expose (no config file needed) cloudflared tunnel --url http://localhost:3000
Once the tunnel is running and the hostname is configured in DNS, Workers can fetch from the tunnelled service like any other origin.
// Worker fetches from on-premise ERP via tunnel export default { async fetch(req, env) { const erpResponse = await fetch( "https://erp.company.com/api/v1/orders", { headers: { "Authorization": `Bearer ${env.ERP_TOKEN}` } } ); return erpResponse; } };
Run cloudflared as a supervised service (systemd, Docker, K8s). Consider running multiple replicas for redundancy.
Anyone who knows the hostname can reach your service. Pair with Cloudflare Access to add identity-aware access control.
Requests go: user → Cloudflare PoP → tunnel → your server. For same-network access, this adds a hop. The trade-off is security for latency.
cloudflared tunnel --url gives you a public URL for a local service in seconds.