DockFlare: Docker labels, Cloudflare Tunnels, and a little less dashboard clicking
Hello everyone, I wanted to share a project I started in 2025 to solve something that kept getting on my nerves in my own homelab. Every time I deployed another container, I found myself back in the Cloudflare dashboard. Add a hostname, point it at the service, configure Access, and remember to clean things up when I stopped using it. Nothing particularly difficult. Just the same work, again and again. Everything else about the service was already in my Docker Compose file. Having its routing and access settings somewhere else felt like one more thing to forget. So I built DockFlare. It watches your Docker containers and uses their labels to manage Cloudflare Tunnel routes, DNS records, and Access policies. You describe what you want alongside your service, and DockFlare takes care of the Cloudflare side. Three labels to get started Once DockFlare is installed and configured, this is enough to expose a simple web container: services: web: image: nginx:alpine restart: unless-stopped networks: - cloudflare-net labels: - "dockflare.enable=true" - "dockflare.hostname=hello.example.com" - "dockflare.service=http://web:80" networks: cloudflare-net: external: true Replace hello.example.com with your own hostname. The example uses the existing cloudflare-net network shared with the tunnel connector. Then start it: docker compose up -d DockFlare picks up the container, configures the tunnel route, and creates the DNS record. No published container port needed. No inbound port to open on your router. The labels tell DockFlare to manage the container, which hostname to use, and where the service lives inside Docker. One detail matters here: these three labels make the service reachable. They do not add authentication. Unless an existing Access policy protects that hostname, it is public. Which brings me to the part I care about just as much as getting a service online. Getting it online is only half the job I want to reach my homelab when Iβm away from home. I also want to decide who gets through to each service. That is where Cloudflare Zero Trust comes in. For this use case, the principle is straightforward: check who someone is and whether they are allowed to access the application. Cloudflare Tunnel connects your service to Cloudflare. Cloudflare Access checks the visitor against your access policy before letting them through. DockFlare manages the tunnel, DNS, and Access configuration together. Letβs use Grafana as an example. Suppose I want grafana.example.com available from anywhere, but only accessible with my own account. In DockFlare, I open Access Policies and create an Access Group called admin-users . I select authenticated access and add my email address to the allowed users. With a login method configured, such as an email one-time PIN, I can then add these labels to my existing Grafana service: labels: - "dockflare.enable=true" - "dockflare.hostname=grafana.example.com" - "dockflare.service=http://grafana:3000" - "dockflare.access.group=admin-users" Grafana needs to be on a network the tunnel connector can reach, just like the first example. When I visit the hostname, Cloudflare checks my Access session and asks me to sign in if needed. Only an account allowed by the policy gets through to Grafana. That gives me an extra access check in front of Grafanaβs own login. The same approach works well for internal dashboards and other web tools you only want yourself, your family, or your team to use. Keep those services behind the tunnel so a separate public port cannot bypass that check. Set up the policy once Once admin-users exists, I can reuse it on another container with the same label: - "dockflare.access.group=admin-users" If I change the group, the services using its reusable Cloudflare policy follow that change. You can also configure a wildcard policy for a hostname such as *.example.com . That gives matching services a default layer of protection, which helps with the whole βIβll configure Access laterβ problem. For a service that should deliberately be public, there is an explicit bypass group: - "dockflare.access.group=public-default-bypass" I like being able to see that decision in the Compose file alongside everything else about the service. A few things I learned along the way Getting the first container online was the easy part. Containers restart. Updates recreate them. Sometimes Docker or the Cloudflare API is temporarily unavailable. All of that needs handling too. DockFlare uses a configurable grace period before cleaning up resources for a stopped container. If the service comes back during that time, the pending cleanup is cancelled. It also checks containers that are already running when it starts, so it does not depend entirely on catching a start event. A lot of work has gone into these less visible parts. Community reports and contributions have helped find cases I would never have encountered in my own setup, and I really appreciate everyone taking the time to report, test, and help improve them. Want to give it a try? Youβll need Docker Compose, a domain managed through Cloudflare, and an API token with the required permissions. The installer starts with: bash <(curl -fsSL https://dockflare.app/install.sh) You can find the setup guide, token permissions, screenshots, and more examples at dockflare.app. DockFlare has grown quite a bit since those first labels. There are now agents for multiple servers, identity provider management, and an optional email suite too. Iβll leave those for another post rather than squeeze everything into this one. The project is open source under GPL-3.0. The code and release notes are on GitHub, and feedback, bug reports, and contributions are always welcome. If you try it in your own setup, let me know how it goes. Iβd also be interested to hear how you manage this today. Labels, config files, or are you still clicking through the dashboard like I was? Happy tunneling, Chris Top comments (0)
Comments
No comments yet. Start the discussion.