DockFlare vs Manual Cloudflare Tunnels: Automate Your Homelab Ingress with Docker Labels (2026)
Reading time: ~12 minutes Audience: Homelab owners running Docker who use (or plan to use) Cloudflare Tunnel and want to stop manually editing YAML files every time they spin up a new service
Introduction: The Tunnel Configuration Bottleneck
Cloudflare Tunnel is one of the most transformative tools in the homelab ecosystem. It eliminates port forwarding, defeats CGNAT, and wraps every service in free SSL — all without exposing your home IP address. We covered the full setup in our Cloudflare Tunnel Homelab Guide, and thousands of homelabbers have since adopted it as their primary ingress solution.
But there is a problem that emerges about three weeks in. You have tunneled your first service — say, Home Assistant. Then you add Jellyfin. Then Immich. Then Uptime Kuma. Each new service means opening your config.yml, adding an ingress block with the correct hostname and service URL, and restarting cloudflared. Your YAML file grows. Your memory of which services are tunneled grows stale. Configuration drift sets in: you decommissioned that Plex container two months ago, but its tunnel rule is still sitting there, pointing at nothing.
This is the problem that DockFlare solves. Instead of maintaining tunnel configuration in a separate YAML file, DockFlare reads Docker labels directly from your containers and synchronizes them with Cloudflare’s API automatically. You define ingress rules where the service lives — in your Docker Compose file — and DockFlare handles the rest.
In this guide, we compare both approaches head-to-head with real Docker Compose examples, a decision framework based on your homelab’s scale, and the trade-offs you need to understand before migrating.
What Is DockFlare?
DockFlare is an open-source Docker container that acts as a bridge between your Docker host and the Cloudflare API. It watches Docker events in real time and translates container labels into Cloudflare Tunnel ingress rules.
Here is what it does under the hood:
- You deploy DockFlare alongside your other containers, mounting the Docker socket.
- You add labels like
dockflare.domain=app.yourdomain.comanddockflare.port=8080to any service you want to expose. - DockFlare detects the label, authenticates to the Cloudflare API using a tunnel token, and creates or updates the ingress rule.
- When you stop the container, DockFlare removes the rule. No orphaned tunnel entries.
The mental model shift is significant: instead of managing tunnels in a separate configuration file that lives outside your service definition, you manage ingress at the service level. The Docker Compose file that defines your application also defines how the outside world reaches it.
Comparison Matrix: DockFlare vs Manual Cloudflare Tunnel
| Aspect | Manual Cloudflare Tunnel (cloudflared) |
DockFlare |
|---|---|---|
| Configuration location | ~/.cloudflared/config.yml (separate file) |
Docker labels inside each service’s docker-compose.yml |
| Adding a new service | Edit YAML → add ingress block → restart cloudflared container |
Add 2 Docker labels → docker compose up -d → done |
| Removing a service | Edit YAML → remove ingress block → restart cloudflared container |
docker compose down → DockFlare removes rule automatically |
| Configuration drift risk | High — manual sync required between running containers and tunnel config | None — labels are the source of truth, auto-synced |
| Learning curve | Low — one config file, well-documented | Moderate — must understand Docker labels and DockFlare’s label schema |
| Multi-host support | Deploy cloudflared on each host, manage per-host configs |
One DockFlare per Docker host (or use Docker Swarm mode) |
| Dependency | Only cloudflared binary |
Docker socket + Cloudflare API access + DockFlare container |
| Failure mode | Tunnel config stays static; services become unreachable if IPs change | If DockFlare goes down, existing tunnels persist; new services won’t be tunneled until it recovers |
| GUI management | Cloudflare Zero Trust dashboard (manual click-based) | None — fully label-driven (infrastructure-as-code) |
| Best for | 1–5 services, static homelab, users who prefer explicit control | 6+ services, frequent additions/removals, Docker Compose-first workflows |
Approach 1: Manual Cloudflare Tunnel with cloudflared
This is the traditional approach. You deploy the cloudflared container, mount a persistent config directory, and define every ingress rule by hand.
Docker Compose
# docker-compose.yml — manual cloudflared
version: "3.8"
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: unless-stopped
command: tunnel run
environment:
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
volumes:
- ./cloudflared-config:/home/nonroot/.cloudflared
networks:
- proxy
Config File (config.yml)
# ./cloudflared-config/config.yml
tunnel: YOUR_TUNNEL_ID
credentials-file: /home/nonroot/.cloudflared/YOUR_TUNNEL_ID.json
ingress:
# Home Assistant
- hostname: ha.yourdomain.com
service: http://homeassistant:8123
# Jellyfin
- hostname: media.yourdomain.com
service: http://jellyfin:8096
# Uptime Kuma
- hostname: status.yourdomain.com
service: http://uptime-kuma:3001
# Immich
- hostname: photos.yourdomain.com
service: http://immich-server:3000
# Catch-all: 404 for unmatched hostnames
- service: http_status:404
Adding a New Service (Manual Workflow)
# 1. Edit config.yml and add a new ingress block
vim ./cloudflared-config/config.yml
# 2. Restart cloudflared to pick up the change
docker restart cloudflared
# 3. Verify the tunnel is healthy
docker logs cloudflared --tail 20
This workflow works. It is battle-tested and thoroughly documented. But at 5 services, the config file is manageable. At 15 services — with some pointing at containers that were renamed, moved to a different Docker network, or decommissioned entirely — it becomes a liability.
Approach 2: DockFlare — Label-Driven Tunnel Automation
DockFlare replaces the manual config.yml with Docker labels. You deploy DockFlare once, then add labels to any service you want to expose.
DockFlare Docker Compose
# dockflare-stack.yml
version: "3.8"
services:
dockflare:
image: ghcr.io/truecharts/dockflare:latest
container_name: dockflare
restart: unless-stopped
environment:
- CLOUDFLARE_TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
- DOCKFLARE_WATCH_INTERVAL=30
- DOCKFLARE_LOG_LEVEL=info
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxy
networks:
proxy:
external: true
Service with DockFlare Labels
# Example service — Home Assistant with DockFlare labels
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
volumes:
- ./ha-config:/config
environment:
- TZ=Asia/Jakarta
networks:
- proxy
labels:
- "dockflare.domain=ha.yourdomain.com"
- "dockflare.port=8123"
- "dockflare.protocol=http"
That is the entire workflow. Add the labels, run docker compose up -d, and DockFlare detects the new container within its watch interval (30 seconds by default). The ingress rule appears in your Cloudflare Zero Trust dashboard and traffic starts flowing.
Removing a Service
docker compose down
# DockFlare detects the container stopped and removes the ingress rule automatically.
# No config file cleanup. No restart needed.
Decision Framework: Which One Should You Use?
Answer these questions to determine which approach fits your homelab:
-
How many services do you expose through Cloudflare Tunnel? If the answer is 5 or fewer, manual
cloudflaredconfiguration is simple enough that DockFlare’s additional complexity may not be worth it. At 6+ services, the automation benefit compounds with every new container. -
How often do you add or remove services? If your homelab is static — the same ten services running for months — manual config works fine. If you experiment frequently, spin up temporary services, or run a CI/CD pipeline that deploys containers, DockFlare’s automatic cleanup prevents configuration rot.
-
Do you already manage everything through Docker Compose? DockFlare fits naturally into a Compose-first workflow where every aspect of a service — ports, volumes, networks, and now ingress — lives in one file. If you use Portainer or a GUI to manage containers, DockFlare’s label approach still works but requires accessing the label editor for each container.
-
Do you need multi-host tunnel support? DockFlare runs per-Docker-host. If you have three Proxmox nodes each running Docker, you need three DockFlare instances (or one if you use Docker Swarm and constrain it to a manager node). Manual
cloudflaredper host is equally straightforward in this scenario. -
How comfortable are you with Docker labels? DockFlare adds a dependency on label-based configuration. If Docker labels are already part of your workflow (for Traefik routing, for example), DockFlare slots in naturally. If you have never touched a Docker label, there is a small learning curve.
Common Pitfalls and Solutions
Pitfall 1: DockFlare Cannot Reach the Cloudflare API
Symptom: DockFlare starts but no ingress rules appear. Logs show 401 Unauthorized or connection refused.
Fix: Verify your tunnel token has the correct permissions. The token must be scoped to the specific tunnel, not the account-wide API token. Generate it from Cloudflare Zero Trust → Networks → Tunnels → [Your Tunnel] → Configure → Credentials. Do not reuse the Global API Key — it has more permissions than DockFlare needs and is a security risk if the environment variable leaks.
Pitfall 2: Container on Wrong Docker Network
Symptom: DockFlare creates the ingress rule, but traffic returns 502 Bad Gateway.
Fix: DockFlare routes traffic using Docker’s internal DNS. The target container must be on the same Docker network as DockFlare, or on a network that DockFlare can reach. The simplest setup: create a dedicated proxy network and attach both DockFlare and every tunneled service to it.
docker network create proxy
Then add networks: - proxy to both DockFlare and every service with dockflare.* labels.
Pitfall 3: Stale Ingress Rules After Container Removal
Symptom: You stopped a container, but its ingress rule is still in Cloudflare Zero Trust. DockFlare did not clean it up.
Fix: DockFlare cleans up rules for containers that are stopped or removed, not containers that are simply unreachable. If you removed the container outside of Docker Compose (e.g., docker rm without docker compose down), DockFlare may not detect the removal event. Use docker compose down for proper lifecycle management. If you still have orphaned rules, remove them manually from the Cloudflare dashboard — DockFlare will not overwrite rules it did not create.
Pitfall 4: Token Exposure in Plain-Text Compose Files
Symptom: You committed your docker-compose.yml to a Git repository with the tunnel token hardcoded.
Fix: Never hardcode secrets. Use an .env file:
# .env (gitignored)
CLOUDFLARE_TUNNEL_TOKEN=eyJ...your-token-here
# docker-compose.yml (safe to commit)
environment:
- CLOUDFLARE_TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
Add .env to your .gitignore. For additional security, consider Docker secrets if you run Docker Swarm, or HashiCorp Vault if you already have it in your stack (see our self-hosted password manager comparison for a lighter-weight secrets management approach).
Integration with Reverse Proxies
DockFlare and manual Cloudflare Tunnels both work alongside reverse proxies. The pattern depends on your architecture:
| Architecture | How It Works | Best For |
|---|---|---|
| Tunnel → Service (Direct) | Cloudflare Tunnel points directly at each container’s port. No reverse proxy involved. | Fewer than 5 services, simple setups |
| Tunnel → Nginx Proxy Manager → Services | Tunnel points at NPM on port 80/443. NPM routes by hostname to backend containers. | Users who want a GUI for proxy host management |
| Tunnel → Traefik → Services | Tunnel points at Traefik. Traefik uses Docker labels to route to backends. | Docker-native, label-driven workflows — pairs naturally with DockFlare |
The Tunnel → NPM → Services pattern is the most popular in the WordForge community. Cloudflare Tunnel provides the secure ingress from the internet. Nginx Proxy Manager handles SSL termination (though it is technically double-encrypted — Cloudflare edge + NPM), hostname routing, and access lists. Each backend container only needs to be on the Docker network, with no port exposure to the host.
For a full walkthrough of this pattern, see our Cloudflare Tunnel Homelab Guide and Nginx Proxy Manager Docker Compose articles.
Already running Traefik? Our reverse proxy comparison guide includes a section on Traefik + Cloudflare Tunnel integration with middleware chains.
Security Considerations
Whether you use DockFlare or manual cloudflared, the security model is the same: Cloudflare sits between the internet and your homelab, and the tunnel is an outbound-only encrypted connection. Neither approach opens ports on your router. Both benefit from Cloudflare’s DDoS protection at the free tier.
However, DockFlare introduces a new attack surface: the Docker socket. Mounting /var/run/docker.sock into any container gives that container root-equivalent access to your Docker host. DockFlare needs read-only access (:ro) to list containers and read labels. It does not need write access.
Mitigations:
- Always mount the Docker socket as read-only:
- /var/run/docker.sock:/var/run/docker.sock:ro - Use a dedicated tunnel token scoped only to the specific tunnel, not an account-wide API token.
- Monitor DockFlare logs for unexpected API calls. DockFlare should only call Cloudflare’s tunnel ingress API.
- Keep DockFlare updated. Subscribe to the DockFlare GitHub releases for security patches.
- Consider
docker-socket-proxyas an alternative to direct socket mounting. It exposes a filtered subset of the Docker API over HTTP, limiting what DockFlare can do. This adds complexity but reduces the blast radius of a compromised container.
FAQ
Does DockFlare replace cloudflared entirely?
No — DockFlare manages tunnel ingress rules (which hostname routes to which service). The actual tunnel connection between your homelab and Cloudflare’s edge is still handled by Cloudflare’s infrastructure. DockFlare communicates with the Cloudflare API to update the ingress configuration. You do not need to run a separate cloudflared container alongside DockFlare — DockFlare handles the API-side management.
Can I use both DockFlare and manual cloudflared at the same time?
Technically yes, but it creates confusion about which system owns which ingress rules. DockFlare only manages rules for containers with dockflare.* labels. Rules defined manually in config.yml are invisible to DockFlare and vice versa. If you are migrating from manual to DockFlare, run DockFlare alongside your existing setup for a week, then decommission the manual cloudflared container once you have verified all services are reachable through DockFlare-managed rules.
What happens if DockFlare crashes?
Your tunnel remains operational. Cloudflare Tunnel ingress rules are stored on Cloudflare’s side, not inside DockFlare. If DockFlare goes down, existing tunnels continue routing traffic. You only lose the ability to add or remove ingress rules until DockFlare recovers. This is a graceful degradation — your services stay online.
Does DockFlare support multiple tunnels?
Yes — you can run multiple DockFlare instances with different tunnel tokens. This is useful if you want to segregate services across different Cloudflare tunnels (e.g., one tunnel for public-facing services, another for admin-only dashboards). Each instance watches all containers on the host but only manages rules for containers whose labels match its configured tunnel.
How does DockFlare compare to Traefik’s Cloudflare integration?
They solve different problems. Traefik is a reverse proxy — it terminates HTTP connections and routes them to backends. DockFlare manages Cloudflare Tunnel ingress rules — it tells Cloudflare “send traffic for app.example.com to this internal service.” If you use Traefik, your tunnel points at Traefik, and Traefik routes to backends. If you use DockFlare without a reverse proxy, the tunnel points directly at each container. The two tools can coexist: DockFlare creates the tunnel ingress rule pointing at Traefik, and Traefik handles internal routing.
The Bottom Line
Manual Cloudflare Tunnel configuration with cloudflared is the right choice for homelabs with 1–5 static services. It is simpler, has fewer moving parts, and the Cloudflare documentation covers every edge case. You edit one YAML file, restart one container, and you are done.
DockFlare becomes the better choice once your homelab crosses the ~6-service threshold, or if you add and remove services frequently. The label-based approach eliminates configuration drift — your Docker Compose files become the single source of truth for both service definition and ingress rules. Services that are removed clean up after themselves. Services that are added come online without touching a separate config file.
Both approaches give you the same end result: secure, SSL-protected access to your self-hosted services from anywhere in the world, without opening a single port on your router. Pick the one that matches your homelab’s complexity.
Want more? If you are building out your homelab ingress stack, these guides take you from zero to production:
- Cloudflare Tunnel Homelab Guide — The complete walkthrough from domain setup to Zero Trust access policies
- Nginx Proxy Manager Docker Compose — GUI-based reverse proxy in 15 minutes
- Traefik vs NPM vs Caddy Comparison — Pick the right reverse proxy for your scale
- Docker Networking Best Practices — Network segmentation, macvlan vs bridge, and proxy network design
- Self-Hosted Backup Strategy 2026 — Back up your configs, labels, and tunnel credentials before disaster strikes