romele / git-trace public
61 commits · 1 branch · 1 tag · last push 8m ago
README.md
# <img src="logo.svg" width="28" valign="middle"> git-trace
**A Git forge you can understand completely in a weekend.**
**git-trace develops git-trace** — its own repo lives on a git-trace
instance, and every push lands over its own SSH transport.
One binary. One SQLite file. The system `git` toolchain. Nothing else.
GitLab became enormous; Gitea aims to be GitHub. git-trace is the
forge a single admin can read end-to-end, audit, and run on a
2 € VPS — while still doing real work: pushes over Smart HTTP *and*
SSH, issues, merge requests, GNU patch-by-email, webhooks, CI,
federation, quotas, and a full browser UX for people who never open
a terminal.
```
Measured on v1.0 idle instance:
git-trace daemon: ~4 MB RSS
git-trace + forge sshd: ~9 MB RSS
```
**Hosting it for yourself? It's free — including production use.**
Free forever for individuals, open-source projects and non-profits.
Every release converts to Apache-2.0 three years after publication.
## Install — 30 seconds
```sh
docker run -d --name git-trace \
-p 8081:8081 -p 2222:2222 -v gt-data:/srv/git-trace git-trace
```
or bare metal:
```sh
make # cc + libsqlite3 + git
./git-trace serve -p 8081 &
echo secretpw | ./git-trace useradd --admin alice
./git-trace mkrepo alice demo "my repo"
git clone http://localhost:8081/alice/demo.git
```
Production bundle (systemd, dedicated forge sshd on :2222, Caddy
reverse proxy, nightly backups): `deploy/install.sh <domain>` —
see [`doc/deploy.md`](doc/deploy.md).
## What it does
- **Git transports**: Smart HTTP + SSH forced commands (gitolite
model — one `git` OS account, per-key forge identity)
- **Browser-first**: create repos, edit/upload files, commit from
the browser — real Git commits, same policy gates as `git push`
- **Collaboration**: issues, merge requests (server-side merges),
GNU patch sets — web *and* `git send-email` via MTA alias
- **Federation**: pull mirrors into `refs/mirror/*` and push mirrors
that publish `refs/heads/*` downstream — event-driven, no polling
- **Ops for sysadmins**: `git-trace doctor` health check,
`backup`/`restore` snapshots, quotas, tier gating, audit log,
static `stagit`-style export, Atom feeds
All of it under the same ACL/policy lattice, fuzzed under
ASan/UBSan, covered by a 294-check e2e suite.
## How it compares
| | git-trace | Gitea | GitLab | SourceHut |
|--------------------|-----------|-------|--------|-----------|
| single binary | yes | yes | no | no |
| runtime deps | sqlite+git| sqlite+git | postgres, redis, rails… | postgres+daemons |
| JS-free UI | yes | no | no | mostly |
| patch-by-email | yes | no | no | yes |
| push federation | yes | partial| yes | limited |
| daemon RSS | ~4 MB | ~150+ MB | ~2 GB | moderate |
## Requirements
Linux · `cc` · `make` · `libsqlite3-dev` · `git`, `tar`, `sh`,
`timeout` at runtime · optional `curl` for HTTPS webhooks.
Windows users: the whole toolchain runs under Docker.
## Docs
| file | contents |
|------|----------|
| [`doc/deploy.md`](doc/deploy.md) | production manifesto + `deploy/` bundle |
| [`doc/architecture.md`](doc/architecture.md) | diagram, design decisions, source layout |
| [`doc/security.md`](doc/security.md) | threat model, ACL matrix, quotas, audit |
| [`doc/web.md`](doc/web.md) | UI surface, web commits, export, SSH keys |
| [`doc/federation.md`](doc/federation.md) | pull/push mirroring, webhooks |
| [`doc/patch-workflow.md`](doc/patch-workflow.md) | GNU patch sets, mail-in, MR convergence |
| [`doc/ci.md`](doc/ci.md) | the minimal CI runner |
| [`doc/portal.md`](doc/portal.md) | external billing/user portal contract |
| [`doc/licensing.md`](doc/licensing.md) | the source-available model, who pays and why |
## Status
**v1.0** — sanitizer-clean, race-hammered, self-hosted since day one.
## License
Hosting it for yourself? **It's free, including production use** —
individuals, open-source projects and non-profits never need a
license. For-profit production use requires a flat commercial
license. Source-available under the Business Source License 1.1
(`LICENSE`); every version converts to Apache-2.0 on its Change
Date. Rationale in [`doc/licensing.md`](doc/licensing.md).