Cloudflare Tunnel: Access Your Web Without Opening Ports
Cloudflare Tunnel (formerly known as Argo Tunnel) uses an outbound connection from your VPS to the Cloudflare network, eliminating the need to expose ports 80/443 to the public internet. Your VPS doesn't need a dedicated public IP, and Cloudflare automatically acts as a DDoS shield. It's available free on the Cloudflare Zero Trust Free plan.
Installing cloudflared
# Install cloudflared on Ubuntu
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb \
-o cloudflared.deb
sudo dpkg -i cloudflared.deb
# Check version
cloudflared --version
Login and Create Tunnel
# Login with Cloudflare (opens browser)
cloudflared tunnel login
# Create a new tunnel
cloudflared tunnel create my-vps-tunnel
# View your tunnel (note the Tunnel ID)
cloudflared tunnel list
Configure Tunnel Config
mkdir -p ~/.cloudflared
nano ~/.cloudflared/config.yml
tunnel: TUNNEL_ID_HERE
credentials-file: /root/.cloudflared/TUNNEL_ID.json
ingress:
# Route domain to local service
- hostname: app.example.com
service: http://localhost:3000
- hostname: api.example.com
service: http://localhost:8080
# Catch-all (required)
- service: http_status:404
# Set up DNS records (via Cloudflare API)
cloudflared tunnel route dns my-vps-tunnel app.example.com
cloudflared tunnel route dns my-vps-tunnel api.example.com
# Test the tunnel (run in foreground)
cloudflared tunnel run my-vps-tunnel
Install as System Service
# Install cloudflared as a service
sudo cloudflared --config /root/.cloudflared/config.yml service install
# Start the service
sudo systemctl enable --now cloudflared
# Check status
systemctl status cloudflared
Verify Tunnel is Working Correctly
# Check tunnel status in Cloudflare dashboard
cloudflared tunnel info my-vps-tunnel
# Verify the service is running
systemctl status cloudflared
# Watch logs in real-time
journalctl -u cloudflared -f
# Test accessing the URL from a browser or curl
curl -I https://app.example.com
ss -tlnp | grep :3000 to verify.
Common Issues & Troubleshooting
Error: "failed to sufficiently increase receive buffer size"
cloudflared requires a large UDP buffer for the QUIC protocol:
sudo sysctl -w net.core.rmem_max=2500000
sudo sysctl -w net.core.wmem_max=2500000
echo "net.core.rmem_max=2500000" | sudo tee -a /etc/sysctl.conf
Tunnel connected but DNS not yet resolving
Your DNS record must be a CNAME pointing to TUNNEL_ID.cfargotunnel.com. Check if the route dns command worked:
# Check DNS record
dig app.example.com CNAME
# If missing, create it again
cloudflared tunnel route dns my-vps-tunnel app.example.com
Service stops after running for a while
This may be caused by expired credentials or network timeouts. Check the logs:
journalctl -u cloudflared -n 100 | grep -i "error\|fatal\|disconnect"
# Try logging in again
cloudflared tunnel login
Website slower than usual after using Tunnel
Cloudflare Tunnel adds a hop through Cloudflare's network, which can add 10–50ms of latency depending on your location. Consider enabling Argo Smart Routing (paid) or check which Cloudflare node is closest to you.
Frequently Asked Questions
What are the limitations on the free Cloudflare Tunnel plan?
The Free plan supports unlimited tunnels and unlimited connections with no SLA or support. Bandwidth is also unlimited (Cloudflare doesn't charge for it). The main constraint is Zero Trust Access policies, which are limited to 50 users on the free plan.
How is it different from a standard Nginx reverse proxy?
A standard Nginx reverse proxy still exposes a public port waiting for connections. With Cloudflare Tunnel, your VPS initiates the connection outbound to Cloudflare instead. This lets you hide your real IP completely and absorbs DDoS attacks at Cloudflare's edge before they even reach your VPS.
Can I use it with SSH or databases?
Yes. Cloudflare Tunnel supports TCP tunneling, so you can access SSH or database ports through Zero Trust Access without opening them publicly. You'll need to run cloudflared on the client side as well.