The simple use case is this:
- You have a machine
- And a containerized app running on that machine.
- Your CI pipeline already builds and publishes images.
- You do not want a full container orchestrator for this workload, but you also do not want to SSH into the box and manually run deploy scripts every time a new image is ready.
That is the space reconD is designed for. reconD is a single-host deployment reconciliation agent. To put it simply, it watches your deployment metadata and deploys the latest version of your app.
A typical workflow for a sample app called my-app
Your CI publishes:
- a container image to GHCR
- a GitHub Release
- a
deployment-metadata.jsonfile that specifies the image, its immutable manifest digest, and the git SHA.
On your virtual machine, reconD periodically asks: "What is the latest desired deployment for dev-my-app or staging-my-app?"
Then it checks: "Is this server already running that digest?" If not, it runs the command you configured:
sh make redeploy-app
That command can be a shell script, a Make target, a Docker command, or something that wraps Docker Compose.
reconD does not try to understand your whole app topology. It does not manage networking, volumes, secrets, scaling, scheduling, ingress, or clusters. That narrowness is intentional. It only owns the reconciliation loop:
- Fetch desired deployment metadata.
- Compare desired digest with local state.
- Inspect the runtime container.
- Apply an optional strategy, such as updating an env file with the new image tag.
- Run your deploy command.
- Wait for health.
- Commit deployment state.
- Roll back if the deployment fails.
- Notify you of deployment status
reconD just keeps asking: "Is this host running the latest version of your app yet?" And if the answer is no, it runs the one command you already trust. It is not Kubernetes. It is not trying to become Kubernetes. It is a small reconciliation loop for single-host deployments, built for the cases where that is exactly enough.
That's the whole model. The server pulls; nothing pushes into it. No inbound SSH from CI, no deploy keys in your pipeline, no open webhook port.
What reconD deliberately doesn't do
reconD doesn't know what Compose is. It runs your command. That command can be docker compose up -d, docker run ..., make redeploy, or a script that runs migrations first. All the knowledge about how to deploy on this particular machine stays in that command, where you can read and test it.
That keeps reconD small. It doesn't manage networks, volumes, secrets, ingress, scaling, or clusters. If a problem needs to understand your app's topology, it belongs in your deploy command, not in the agent.
Failure handling
The interesting part of deployment automation isn't the happy path. It's what happens with a bad release.
Bounded retries. Forward deployments and rollbacks retry with exponential backoff and jitter, up to limits you set:
deployment_retry:
max_retry_forward_deployment: 3
max_retry_rollback: 2
It remembers failures. Without this, a bad image gives you an endless loop: deploy, fail the health check, roll back, next poll, deploy the same bad image again. reconD records the failed digest in its state file and doesn't try it again automatically. If the rollback succeeds, your service is back up, but the failed version stays blocked. Pushing a newer release unblocks deployment.
It survives restarts. The current deployment, the previous one (the rollback target), and any terminal failure live in one JSON state file on disk. Restart the agent, or the host, and it picks up where it left off.
You can also point reconD at a Slack webhook to hear when a deployment starts, succeeds, or fails.
Try it
If you run apps on a single server and want deployments that are pulled, health-checked, and can roll back, without adopting a platform, give it a try:
Issues, ideas, and "this broke on my distro" reports are all welcome.
Top comments (0)