Sidecar daemon written in Go that replicates git repositories across nodes using git bundle streaming over gRPC
  • Go 98.9%
  • Shell 0.6%
  • Dockerfile 0.5%
Find a file
Kreato 7302d5f8e1
All checks were successful
Build and push / build (push) Successful in 32m3s
fix: repoint dangling HEAD after bundle apply
2026-06-29 21:47:22 +03:00
.forgejo/workflows cmd 2026-06-29 00:58:00 +03:00
cmd fix: stream git bundles to avoid OOM-killing the sidecar on large repos 2026-06-28 20:31:26 +03:00
internal fix: repoint dangling HEAD after bundle apply 2026-06-29 21:47:22 +03:00
proto chore: rename module to src.krea.to/infra/gitsyncd, add Forgejo Actions CI 2026-06-26 01:10:13 +03:00
.gitignore feat: add main entrypoint, Dockerfile, fix ListRepos recursion 2026-06-25 17:21:31 +03:00
Dockerfile fix: copy gitsyncd-hook from Go process at startup (no /bin/cp in scratch); mount shared volume in forgejo container 2026-06-26 02:29:07 +03:00
go.mod test: replace exec.Command(git) in test setup with go-git 2026-06-26 01:51:50 +03:00
go.sum test: replace exec.Command(git) in test setup with go-git 2026-06-26 01:51:50 +03:00
LICENSE add LICENSE and update README to remove dead docs 2026-06-26 04:37:59 +03:00
README.md add LICENSE and update README to remove dead docs 2026-06-26 04:37:59 +03:00

gitsyncd

gitsyncd is a Go sidecar daemon that replicates git repositories across Forgejo pods via git bundle streaming over gRPC. It eliminates the need for NFS/shared storage in multi-replica Forgejo deployments, giving each pod a local-path PVC with real-time replication between peers.

Works with any git server that fires post-receive hooks. Designed for and tested with Forgejo on Kubernetes. Currently is used on src.krea.to.

  • Multi-writer: all pods accept pushes. Git's non-fast-forward rejection handles conflicts. No leader election.
  • Live-peer quorum: push returns only after all currently-live peers ACK. Down peers are excluded from quorum.
  • Async S3 WAL (optional): bundles uploaded to S3 in background after push returns. Zero added latency.
  • Background reconciler: 30s interval safety net catches missed replications and bootstraps new nodes.

How it works

User pushes → Forgejo updates refs → post-receive hook fires
  → shell script sends ref data to gitsyncd via Unix socket
  → gitsyncd creates git bundle (objects changed)
  → streams bundle via gRPC to all live peers concurrently
  → waits for all live peers to ACK
  → returns OK to hook → user sees successful push

Async (background): bundle copied to S3 for down-node recovery

Quick start

Build:

docker build -t gitsyncd .

Deploy alongside Forgejo as a StatefulSet sidecar. [TBD]

Architecture

            Forgejo Pod
  +-----------------------------+
  |  Forgejo     gitsyncd       |
  |  reads git     (Go daemon)  |
  |  from local                 |
  |       \            /        |
  |        local-path PVC       |
  +-----------------------------+
       | gRPC :9999    | socket
       v               v
   headless service   async S3
   (peer discovery)   WAL upload

gRPC protocol

service GitSync {
  rpc ReplicatePush(stream PushChunk)       returns (Ack);
  rpc ReplicateRepoCreate(stream Bundle)    returns (Ack);
  rpc ReplicateRepoDelete(RepoID)           returns (Ack);
  rpc GetRepoHashes(Empty)                  returns (RepoHashes);
  rpc FetchRepo(RepoID)                     returns (stream BundleChunk);
  rpc HealthCheck(Empty)                    returns (HealthStatus);
}

Configuration

All via environment variables:

Variable Default Description
GITSYNCD_REPOS_DIR /repos Path to git repos root
GITSYNCD_SOCKET /shared/gitsyncd.sock Unix socket shared with Forgejo
GITSYNCD_GRPC_PORT 9999 gRPC listen port
GITSYNCD_PEER_TIMEOUT 5s Per-peer ACK timeout
GITSYNCD_PEER_HEALTH_TIMEOUT 2s Health check timeout
GITSYNCD_RECONCILE_INTERVAL 30s Reconciler loop interval
POD_IP (required) Pod IP for self-identification
GITSYNCD_S3_* (unset) S3 WAL config (endpoint, bucket, region, key, secret)

Project structure

cmd/gitsyncd/         daemon entrypoint
cmd/gitsyncd-hook/    minimal hook binary
internal/
  server/             gRPC server, Unix socket listener, health
  replicate/          push, create, apply, quorum
  s3wal/              async WAL queue, uploader, S3 replay
  reconcile/          background reconciler (hash compare + sync)
  discovery/          headless service peer discovery
  git/                bundle, refs, hook helpers
  config/             env var config
proto/gitsync.proto   gRPC service definition
docs/design.md        full architecture spec

License

MIT