The pitch for Hostbox is intentionally short: push code, get a URL, on your own server. The implementation has spent a lot of time reminding me how much work can hide inside eight words.
A deployment starts with a commit, but even that creates questions. Did we build the exact commit shown in the dashboard? What happens if the branch moves while a worker is cloning it? Can a cancelled build later report itself as failed? Simple product promises become state machines very quickly.
A deployment is a chain of custody
Hostbox has to accept an event, persist the job, fetch the intended source, run an isolated build, validate the output, put the artifact in the right place, update Caddy, and only then call the deployment ready. Every hand-off needs an identity and a recoverable state.
The happy path is important. The halfway path is where most of the design lives.
Boring components are a feature
I chose a Go control plane, SQLite in WAL mode, Docker for build isolation, and Caddy for routing and certificates. None of those choices are surprising on their own. Together they keep the operational model understandable: one small server, a database file, build containers that disappear, and a proxy that is very good at HTTPS.
The button should stay simple
Users should not need to think about worker pools, route reconciliation, commit verification, or crash recovery just to publish a static site. The system has to think about those things precisely so the user does not.
That is the kind of backend work I like: a lot of careful machinery in service of a sentence that stays short.