gitmote / docs / architecture / README.md · history · branches
3639 bytes · raw
A tiny single-container Go server that speaks git's smart-HTTP protocol, stores repositories in S3-compatible object storage, and keeps its mutable metadata (refs, users, keys, access) in s3lite (SQLite with S3-backed durability). The container itself is disposable — all durable truth lives in S3 + s3lite — so it runs as a single writer that scales to zero: it wakes on a request, serves, and idles back down.
Built for self-hosting a handful of repos, with the door open to invite a few collaborators and to accept commits authored through a web UI. It is explicitly not trying to be GitHub at scale.
Design priorities, in order: safe → simple → cheap-to-idle → fast. Where they conflict, the earlier one wins. Pragmatic beats pure.
"Git on S3" is easy except for one thing — atomic ref updates under concurrent writers. Everything else is either immutable or single-writer-safe. So we split git's storage along the axis that decides which store each half wants, and we let real git do the parts that are hard to reimplement:
| Data | Property | Store |
|---|---|---|
| Objects & packs | Immutable, content-addressed, bulky (~90% of bytes) | Plain S3 — synchronous PUT, re-PUT of the same hash is idempotent |
| Refs, users, keys, ACLs, repo registry, web-edit state | Small, mutable, need transactional CAS | s3lite — a ref update is one SQL transaction |
| Everything git actually computes (packing, negotiation, merge-base, …) | Hard to reimplement correctly | Stock git on ephemeral local disk |
The payoff: the single genuinely-hard problem collapses into a one-line SQL compare-and-swap, on a database already trusted in production — plain SQLite (via s3lite) — with no database to operate.
The rest of the architecture is split by concern:
| Doc | What's in it |
|---|---|
| storage.md | The components that make up the container, and where each kind of data lives — S3 object layout and the s3lite schema. |
| request-flows.md | The read path (clone/fetch) and the write path (push, and the compare-and-swap that makes it safe). |
| safety.md | The concurrency & safety model — single writer, the content-before-pointer ordering invariant, and the accepted write-loss window. |
| auth.md | Authentication and transport — smart HTTP + personal access tokens today, SSH deferred. |
| ci.md | CI — running .gitmote/workflows on push: the dispatch seam, the one-runner-three-substrates model, act self-hosted vs. nested, secrets, and the no-in-Job-image-builds limitation. |
| alternatives.md | Approaches considered and rejected or deferred, with the reasoning. |
| open-questions.md | Unsettled decisions — the superset that links into ../notes/. |
Speculative, non-committal future directions live in
../evolution/ — read them as ideas, not plans.