I built a tool called ComposeFlux to manage Docker Compose deployments across my homeservers using GitOps. If you want to know the backstory — what I was using before, what alternatives I tried, and why I built it:
Part 1: My Homeservers, Ansible, and the Pain Points
Part 2: Searching for the Right Tool — Komodo, Dockhand, and Beyond
Part 3: ComposeFlux — A Lightweight GitOps Tool for Docker Compose
Introduction
I manage 2 homeservers and a few cloud VMs, running around 15+ Docker Compose apps — from Traefik and Jellyfin to Immich and Prometheus. Over time, deploying and managing these stacks across multiple servers became painful, especially when the same app (like Traefik) needed to be configured on multiple servers.
After using Ansible playbooks for almost 2 years and evaluating tools like Komodo and Dockhand, I built my own tool: ComposeFlux.
ComposeFlux is a lightweight, headless GitOps tool for Docker Compose. It continuously polls a Git repo, detects changes in your compose files, and deploys only the stacks that changed. No backend database, no UI — just Git and Docker Compose.
Here are the key features:
- True GitOps — Push to Git, deployment happens automatically
- Smart change detection — Only redeploys stacks whose compose file hash changed
- External secrets support — Integrates with Bitwarden and Infisical
- Pure Go — Uses the Docker Compose SDK directly, no shell commands
- Flexible config — Startup order, shared env vars, minimal YAML config
- Automatic image updates — Checks registries on a cron schedule and updates containers via the Compose SDK
- Lightweight — Single binary, no database
For the full feature breakdown, check out Part 3 of my blog series, or the ComposeFlux docs.
Now, let me show how I actually use it.
Git Repo Structure
I use Docker Compose’s “include” feature to create a base/overlay structure — similar to Kustomize if you’re familiar with Kubernetes.
The stacks folder holds generic, reusable docker compose files. The servers folder contains a dedicated folder for each server, where apps just reference the base compose files:
.
├── servers # Overlay — each server has a folder
│ ├── helium # My Lenovo homeserver
│ │ ├── gocron
│ │ ├── immich
│ │ ├── it-tools
│ │ ├── n8n
│ │ ├── node-exporter
│ │ ├── omni-tools
│ │ ├── squoosh
│ │ ├── stack.yml
│ │ ├── traefik
│ │ └── zeroclaw
│ ├── wg1-ams # Oracle Cloud VM in Amsterdam
│ │ ├── adguardhome
│ │ ├── authelia
│ │ ├── stack.yml
│ │ ├── traefik
│ │ └── wg-easy
└── stacks # Base — reusable compose files
├── actualbudget
│ └── compose.yml
├── traefik
│ ├── compose.yml
│ └── README.md
├── qbittorrent
│ ├── compose.config.yml
│ ├── compose.scripts.yml
│ ├── compose.yml
│ └── README.md
└── zeroclaw
├── compose.yml
└── README.md
This structure means I fix a Traefik config once in stacks/traefik/compose.yml, and every server that includes it gets the update.
I also use Docker Compose Configs to store app configuration directly inside compose files, so that ComposeFlux’s hash-based change detection can pick up config changes too.
Deploying ComposeFlux with Ansible
I use an Ansible playbook to copy and deploy ComposeFlux on each target server. The playbook copies the ComposeFlux docker compose file to the server and brings it up.
There is a work-in-progress Ansible role to manage this deployment more cleanly.
See the Multi-Server Setup docs for how ComposeFlux uses the repo structure above to manage apps across servers.
GitOps in Action
ComposeFlux continuously polls a Git repo on a specific branch, watching a specific directory. For example, ComposeFlux deployed on the server wg1-ams watches the servers/wg1-ams/ directory:
.
├── servers
│ ├── wg1-ams # ComposeFlux on "wg1-ams" watches this directory
│ │ ├── adguardhome
│ │ ├── authelia
│ │ ├── stack.yml
│ │ ├── traefik
│ │ └── wg-easy
└── stacks
└── ...
Whenever I push changes to this directory — boom, ComposeFlux picks up the change and deploys it on the server. No manual SSH, no running playbooks, no copy-pasting configs.
Testing Before Merge with Auto-Dev
Here’s the part I’m most happy about.
Imagine you create a PR to add a new docker compose file for an app, say “IT Tools”. The PR diff looks good, you merge to main. But you didn’t actually test the deployment on any server before merging. ComposeFlux picks up the change from main, tries to deploy, and fails because of some wrong config. Not great.
To solve this, I use autodev-action — an open source GitHub Action from my employer. We use this internally every day for GitOps repos.
Here’s how it works: when you add a dev label to your PR, the action merges your feature branch changes into a dev branch (configurable) and also syncs changes from main. On the server, ComposeFlux is configured to watch the dev branch instead of main.
My deployment flow:
- Create a PR and review the diff
2. Add the dev label
Here are the action logs:
3. ComposeFlux deploys on the server
veerendra@hydrogen:~$ docker logs composeflux
time=2026-05-02T17:31:14+02:00 level=DEBUG msg="Fetch git updates" remote_sha=bdb996d local_sha=a1c40f7 updates=true
time=2026-05-02T17:31:16+02:00 level=DEBUG msg="Adding secrets to cache" count=17
time=2026-05-02T17:31:16+02:00 level=DEBUG msg="Adding env vars to cache" count=7
time=2026-05-02T17:31:16+02:00 level=INFO msg="Stack hash changed, redeploying" stack_name=homer
time=2026-05-02T17:31:16+02:00 level=INFO msg="New stack detected" stack_name=it-tools
time=2026-05-02T17:31:17+02:00 level=INFO msg="Deploying stacks" count=2 order=homer,it-tools
time=2026-05-02T17:31:26+02:00 level=INFO msg="Successfully deployed the stack" stack_name=homer
time=2026-05-02T17:31:37+02:00 level=INFO msg="Successfully deployed the stack" stack_name=it-tools
I can confirm the app appeared in my Homer dashboard:
4. Everything works — merge the PR to ** main**
This gives me confidence that every deployment is tested before it hits production. Just like how we do it at work, but for my homeservers.
Wrapping Up
This setup has been running smoothly for my homeservers and cloud VMs. The combination of Git as the source of truth, ComposeFlux for automated deployments, and the auto-dev workflow for testing before merge gives me a workflow that feels professional — even for a home setup.
If you’re managing Docker Compose apps across multiple servers and tired of manual deployments, give ComposeFlux a try. Check out the documentation to get started.





Top comments (0)