Discovering Komodo: Git-Synced Infrastructure Without the Ceremony

How I moved from clicking through container deployments to a small, reviewable Git workflow with Komodo, Docker Compose, and Resource Sync.

I discovered Komodo while looking for a better way to operate a small collection of Docker Compose services. I wanted the convenience of a web interface—status, logs, restarts, deployments—without turning my setup into a platform engineering project. More importantly, I wanted Git to remain the source of truth.

Komodo sits in an interesting middle ground. It is more operational than a collection of shell scripts, but much lighter than a full orchestration platform. Its model is easy to understand: Core provides the control plane and web interface, while a small Periphery agent connects each managed server.

The architecture that clicked for me

Core is the place where resources are defined and actions are coordinated. It stores the inventory, exposes the UI and API, receives webhooks, and decides what should run. Periphery runs close to the workloads. It performs the host-level work: cloning repositories, running Compose commands, reading logs, and reporting system information.

For a first test, both components can live on one machine. I preferred separating the control plane from the application host conceptually, even if the initial lab was small. That makes the trust boundary clearer and leaves room to add another server later without redesigning everything.

Installing Core

I started with the Docker Compose installation from the Komodo documentation. The important part was not copying a large example verbatim, but deciding where persistent state, secrets, and ingress belonged in my own layout. I placed Core behind an existing reverse proxy at komodo.example.com, kept its database on persistent storage, and supplied sensitive values through environment variables rather than committing them.

Before connecting anything else, I checked four things: the HTTPS endpoint worked, the database survived a container restart, the UI could create an administrator, and the Core logs remained clean. This small pause was useful. Adding agents and Git automation before confirming persistence would have made later failures much harder to classify.

Connecting a server with Periphery

The next step was onboarding infra-host-01. Komodo generates an onboarding key in Core; that key is passed to the Periphery installation on the target server. Once the agent connects, Core shows the server state and can attach resources such as Stacks, Repos, and Deployments to it.

Periphery can run as a container or as a system service. I chose the installation style based on one practical question: which process needs access to Docker, Compose files, and checked-out repositories? Whatever the answer, the agent should receive only the filesystem paths and privileges it actually needs.

Moving the configuration into Git

The feature that changed Komodo from a useful dashboard into an infrastructure workflow for me was Resource Sync. Resources can be declared in TOML, stored in a repository, reviewed like application code, and synchronized into Core. The UI still shows the proposed changes before they are applied, so Git does not remove visibility—it improves it.

[[server]]
name = "infra-host-01"
description = "Primary application host"

[server.config]
address = "https://agent.example.com:8120"
enabled = true

[[stack]]
name = "notes-app"
description = "Example Compose application"

[stack.config]
server = "infra-host-01"
git_provider = "git.example.net"
git_account = "automation-user"
repo = "example/infra-config"
run_directory = "stacks/notes-app"
file_paths = ["compose.yaml"]

This example intentionally uses fictional names. The useful pattern is the relationship: a Stack points to a server, a Git provider account, a repository, a working directory, and one or more Compose files. Komodo clones the repository on the target host and deploys from that checkout.

Configuring the Git provider

Private repositories need a Git provider account. In Settings → Providers, I added the provider domain, a dedicated automation username, and a narrowly scoped access token. The token stays in Komodo; the TOML refers only to the provider and account names. For a provider domain, Komodo expects a hostname such as git.example.net, without the https:// prefix.

I used a machine account rather than a personal token. That makes ownership explicit, simplifies rotation, and avoids coupling deployments to one person's access. Read-only repository access is sufficient when Komodo only pulls configuration. Write access is needed only for features that deliberately commit changes back to Git, such as Managed Mode.

Creating the Resource Sync

I then created a Resource Sync pointing to example/infra-config and selected the TOML files that describe the environment. Komodo periodically checks those files and computes a diff against its current resources. A sync can create or update servers, stacks, repositories, procedures, and other resources. It can also filter resources by tags, which is useful when one repository describes several environments.

[[resource_sync]]
name = "homelab-sync"

[resource_sync.config]
git_provider = "git.example.net"
git_account = "automation-user"
repo = "example/infra-config"
branch = "main"
resource_path = ["komodo/resources.toml"]

My preferred first run was manual: refresh the sync, inspect the proposed actions, and apply them only after the diff matched my expectations. Once that loop was predictable, I added a Git webhook so pushes to the configured branch could trigger a refresh or sync. Komodo validates supported webhook signatures using a shared secret, and branch filtering prevents unrelated pushes from triggering an action.

What I learned

The biggest improvement was not automatic deployment. It was having one reviewable path from intent to runtime. A Compose change, a new Stack definition, and the files that should trigger redeployment can live in the same commit. Komodo then exposes the operational side of that change: the diff, execution history, container state, and logs.

I also learned to avoid enabling deploy-on-push too early. A successful Git sync proves that Komodo understood the declarations; it does not prove that an application is healthy. I now add health checks, verify persistent paths, and test a real request after deployment before treating a change as complete.

Komodo did not replace Docker Compose or Git in my setup. It connected them. That is exactly what I wanted: familiar files, visible operations, and enough automation to remove repetitive work without hiding how the system runs.