Setting Up Cloudflare Tunnel for Secure Self-Hosting

How to expose your Docker apps securely with Cloudflare

Self-hosting your apps at home or on a VPS is powerful — but exposing them securely to the internet can be a challenge. Public IPs, router configs, and HTTPS certificates are often a hassle. This is where Cloudflare Tunnel comes in: a secure, reliable way to expose services without opening ports or handling HTTPS yourself.

In this post, I’ll show you how to set up Cloudflare Tunnel to expose your Dockerized web apps to the internet, securely and for free.


🔒 Why Use Cloudflare Tunnel?

  • No port forwarding: Avoid opening your firewall or router.
  • Free HTTPS: Automatic TLS certificates via Cloudflare.
  • Zero Trust controls: Protect your internal services with identity-based access.
  • High availability: Cloudflare’s edge network acts as a global reverse proxy.

⚙️ Prerequisites

  • A Cloudflare account
  • Your domain managed by Cloudflare (e.g. your-domain.com)
  • A self-hosted server with Docker installed
  • Your app running on a local port (e.g. a web app at localhost:8080)

🛠️ Step-by-Step Setup

1. Install cloudflared

Download the Cloudflare Tunnel client:

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb

Or via package manager:

sudo apt install cloudflared

2. Authenticate with Cloudflare

Run:

cloudflared tunnel login

This opens a browser and lets you authorize the tunnel for your domain.


3. Create the Tunnel

cloudflared tunnel create my-tunnel

This creates a tunnel ID and credentials in ~/.cloudflared/.


4. Create the Config File

Create ~/.cloudflared/config.yml:

tunnel: my-tunnel
credentials-file: /home/youruser/.cloudflared/my-tunnel.json

ingress:
  - hostname: your-domain.com
    service: http://localhost:8080
  - service: http_status:404

This maps the public domain (your-domain.com) to your internal app (localhost:8080).


5. Add a CNAME Record

In your Cloudflare DNS dashboard:

  • Type: CNAME
  • Name: app
  • Target: your-tunnel-id.cfargotunnel.com
  • Proxy status: Proxied (orange cloud)

Alternatively, run:

cloudflared tunnel route dns my-tunnel app.eztalo.com

6. Run the Tunnel

Start it manually:

cloudflared tunnel run my-tunnel

Or run as a service:

sudo cloudflared service install
sudo systemctl enable --now cloudflared

🐳 Bonus: Using with Docker Compose

Run cloudflared in a sidecar container:

# docker-compose.yml
services:
  web:
    image: myapp
    ports:
      - "8080:80"

  tunnel:
    image: cloudflare/cloudflared:latest
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=<your-tunnel-token>
    restart: unless-stopped

To get the TUNNEL_TOKEN, run:

cloudflared tunnel token my-tunnel

✅ Verify Everything Works

Visit https://your-domain.com in your browser. Your Docker app should be live, secured with HTTPS, and accessible anywhere — without exposing your home network or VPS ports.


🔐 Optional: Secure with Cloudflare Zero Trust

Add an identity-based access rule:

  1. Go to Cloudflare Zero Trust Dashboard
  2. Create an Access Policy for your hostname (e.g. your-domain.com)
  3. Require users to log in with Google, GitHub, or email

This is perfect for internal dashboards and tools.


🧠 Final Thoughts

Cloudflare Tunnel is a powerful and easy way to make your self-hosted Docker apps securely available to the internet. Whether you’re hosting dashboards, dev tools, or full-blown web apps — it saves you time, hassle, and makes things just work.

Scroll to Top