Gitfed
bastien-mrq/gitfed / README.md
README.md Code Preview
**Languages:** English · [Français](README.fr.md)

# gitfed

*A self-hosted, federated git server for people who want their code and their
data to stay theirs — without losing the ability to work with anyone,
wherever they host.*

---

## Why gitfed exists

Most git-hosting options ask for a trade: keep your code somewhere you don't
control, or give up the ability to collaborate with anyone outside your own
server. gitfed exists to remove that trade-off.

- **Ownership** — your repositories, your users, your database, on hardware
  you control. No platform can throttle your access, mine your code, or shut
  you out.
- **Federation** — your instance can trust other people's instances, the way
  mail servers trust each other. Someone on a completely different gitfed
  instance can be granted access to one of your repos without ever creating
  an account with you.
- **Control** — every repo is explicitly public or private, every
  collaborator has an explicit role (read/write/admin), and every trust
  relationship between instances is explicit too — nothing is granted by
  default just because a request showed up.

gitfed isn't trying to out-feature GitHub or GitLab. The web UI (file
browser, self-service repos, admin panel) exists to make the identity model
usable day to day — the identity model itself is the point.

## How it works, in one paragraph

Each gitfed instance runs its own certificate authority. When you push or
pull, your home instance signs a short-lived SSH certificate that says who
you are. Any instance that has chosen to trust your home instance's
certificate authority accepts that certificate — no second account, no
shared password, no per-instance registration. The full walkthrough is in
[`docs/HOW_IT_WORKS.en.md`](docs/HOW_IT_WORKS.en.md), and the same
explanation, with diagrams, is served live at `/security` on any running
instance.

## What's included

- **`gitfed-server`** — SSH server (git operations + certificate issuance)
  and the `/.well-known/gitfed.json` federation endpoint.
- **`gitfed-web`** — the web UI: a public repo browser, and, behind a
  password login, self-service (your own keys and repos), merge requests
  with review and a discussion thread, and an admin section, in French or
  English.
- **`gitfed-tui`** — a terminal admin tool; the only way to bootstrap the
  first account.
- **`gitfed-renew-cert`** — a small client tool to renew your own
  certificate before it expires.

## Learn more

| Doc | What's in it |
|---|---|
| [`INSTALL.md`](INSTALL.md) *(French)* | Step-by-step install on a brand new VPS, from an empty machine to a working instance — no k3s/cert-manager assumed already set up. |
| [`FEDERATION.md`](FEDERATION.md) *(French)* | How to actually get two instances collaborating: prerequisites, granting access, the trust-approval step that's easy to miss, and getting a certificate. |
| [`docs/HOW_IT_WORKS.en.md`](docs/HOW_IT_WORKS.en.md) | The federation/identity model end to end: certificates, trust store, ACLs, a real push walked through step by step. |
| [`docs/ARCHITECTURE.en.md`](docs/ARCHITECTURE.en.md) | How the code is organized: the four binaries, the `internal/` packages, why there's an admin RPC socket, the Kubernetes topology. |
| [`docs/security/AUDIT.md`](docs/security/AUDIT.md) *(French)* | The pre-production security audit and what was fixed as a result. |
| [`docs/security/AUDIT-2026-07-29.md`](docs/security/AUDIT-2026-07-29.md) *(French)* | Follow-up audit covering the anonymous HTTPS clone, federated notifications and pinned repos added afterward. |
| [`docs/security/AUDIT-2026-07-29b.md`](docs/security/AUDIT-2026-07-29b.md) *(French)* | Audit of merge requests — found and fixed a critical, unauthenticated argument-injection bug (arbitrary file write via crafted commit hashes/branch names), plus two lower-severity fixes. |
| [`DESIGN.md`](DESIGN.md) *(French)* | The original design rationale — the "why" behind the architecture, written before implementation started. |
| [`ROADMAP.md`](ROADMAP.md) *(French)* | What was deliberately left out of V1 and why, versus what's rejected outright versus what might come later. |
| [`CHANGELOG.md`](CHANGELOG.md) | Version history (also served at `/changelog` in the web UI). |
| [`THIRD_PARTY_LICENSES.md`](THIRD_PARTY_LICENSES.md) | Every Go dependency and its license. |

## Running it locally

```sh
go build -o bin/gitfed-server ./cmd/gitfed-server
go build -o bin/gitfed-web    ./cmd/gitfed-web
go build -o bin/gitfed-tui    ./cmd/gitfed-tui

./bin/gitfed-server -init localhost -data-dir data -config gitfed.json
# edit gitfed.json if you want different ports (defaults: ssh :2222, http :8443)
./bin/gitfed-server -config gitfed.json &

./bin/gitfed-tui -config gitfed.json
# Users -> a (add user): username, your SSH public key, a password, admin: y

./bin/gitfed-web -config gitfed.json &
# open http://localhost:8088, log in with what you just created
```

Cloning/pushing always goes over SSH:

```sh
git clone ssh://git@localhost:2222/<user>/<repo>
```

## Deploying for real

Starting from a brand new VPS with nothing on it yet (no k3s, no
cert-manager)? [`INSTALL.md`](INSTALL.md) *(French)* walks through all of
that from scratch, step by step — or run `gitfed-install`
(`go build -o gitfed-install ./cmd/gitfed-install`), a terminal wizard that
does the same steps for you, detects what's already installed, and
diagnoses a stuck `ErrImageNeverPull` pod on its own.

Already have k3s/Traefik/cert-manager running? The full walkthrough —
manifests, why the pod is shaped the way it is, DNS, bootstrapping the
first account — is in
[`deploy/k8s/README.md`](deploy/k8s/README.md). Every update after the first
should go through [`deploy/update.sh`](deploy/update.sh), which bumps the
version, builds and imports a tagged image, and rolls it out:

```sh
# add a "## X.Y.Z" section to CHANGELOG.md describing the change first
deploy/update.sh          # patch bump
deploy/update.sh minor    # or: major, or an explicit X.Y.Z
```

## Backups

Everything that matters lives on one persistent volume: the database (users,
repos, ACLs, sessions, trust store, audit log, certificate revocations), the
instance's CA key, the SSH host key, and the bare repos themselves. Losing
the CA key invalidates every certificate this instance has ever issued and
breaks every federated trust relationship pointing at it — there's no
recovery short of everyone re-establishing trust from scratch. Back up the
whole volume, not just the git data.

For the Kubernetes deployment, [`deploy/backup.sh`](deploy/backup.sh)
automates this — snapshots the whole volume to a timestamped tarball
downloaded off the server, with pruning. The restore procedure is in
[`deploy/k8s/README.md`](deploy/k8s/README.md#backups).

## License

[GNU AGPLv3](LICENSE) — the network-copyleft license: if you run a modified
version of gitfed as a service for other people, you're required to make
your modified source available to them, even if you never distribute the
binary. That's a deliberate choice, not a default — it's meant to keep any
gitfed-derived instance's improvements flowing back to the ecosystem
instead of being closed off behind a hosted service.