Home Services Blog Contact

Setting Up Cloudflare Tunnel: Secure Access Without Opening Router Ports

A step-by-step guide to setting up Cloudflare Tunnel with Docker. Securely expose your local services to the internet without configuring your router.

Cloudflare Tunnel (also known as cfd or cloudflared) is a revolutionary solution for exposing local services to the internet securely - without needing to open any ports on your router.

In this tutorial, I'll show you how to set up and configure Cloudflare Tunnel using Docker.

Why Cloudflare Tunnel?

Traditionally, exposing services to the internet required port forwarding on your router (NAT). This comes with several drawbacks:

  • Insecure - anyone can potentially access your services
  • Cumbersome - every change requires router configuration
  • Problematic - with dynamic IPs, you need DDNS

Cloudflare Tunnel solves all these problems:

  • 🔒 Secure - only allowed domains can access your services
  • 🌐 No router setup - no port forwarding needed
  • Fast - QUIC protocol for low latency
  • 🛡️ DDoS protection - Cloudflare filters malicious traffic
  • 🔑 Free - for most use cases

Prerequisites

  • A Cloudflare account with a domain
  • Docker and Docker Compose on your server
  • A service you want to expose

Step 1: Create a Tunnel

First, create a new Cloudflare Tunnel. The easiest way is via the Cloudflare Dashboard:

  1. Go to Zero Trust DashboardNetworksTunnels
  2. Click Add tunnel
  3. Choose Cloudflare Tunnel as the type
  4. Give your tunnel a name (e.g., my-server)
  5. Save the generated token

Step 2: Set Up Docker Compose

Create a docker-compose.yml file:

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    network_mode: host
    restart: unless-stopped
    environment:
      - TUNNEL_TOKEN=your_tunnel_token_here
    command: tunnel run

Replace your_tunnel_token_here with the token from Step 1.

💡
Tip: With network_mode: host, you can reach services via localhost. This is simpler than host.docker.internal.

Step 3: Configure Ingress Rules

Ingress rules determine which domain points to which service. You can configure this in the Dashboard or via the API.

Example configuration:

ingress:
  - hostname: example.com
    service: http://localhost:3000
    originRequest:
      noTLSVerify: false
  - hostname: admin.example.com
    service: http://localhost:8080
    originRequest:
      noTLSVerify: false
  - service: http_status:404

The last rule http_status:404 catches all undefined requests.

Step 4: Create DNS Records

For each subdomain you want to use, create a CNAME record:

  • Type: CNAME
  • Name: example.com (or subdomain)
  • Content: {tunnel-id}.cfargotunnel.com
  • Proxy status: Proxied

Step 5: Test

Start the container:

docker compose up -d

Check the logs:

docker logs cloudflared

If everything works, you should see:

INF Registered tunnel connection connIndex=0
INF Updated to new configuration

Your domain should now be accessible through Cloudflare!

Advanced Options

Multiple Services

You can configure as many subdomains as you need. Remember to create a CNAME record for each one.

SSL/TLS

Cloudflare handles SSL certificates automatically. No extra configuration needed.

Websocket Support

Cloudflare Tunnel supports websockets out of the box. No special configuration for most applications.

Conclusion

Cloudflare Tunnel is an elegant solution for exposing self-hosted services securely and easily. No router configuration, no security risks from open ports, and you get Cloudflare's DDoS protection and caching for free.

Need help with setup? Contact us - we're happy to assist with Cloudflare Tunnel and other self-hosted solutions!

Need Help with Setup?

We'd be happy to assist you with Cloudflare Tunnel and other self-hosted solutions.

Get in Touch

Article updated on February 26, 2026