17789db11 days ago155 CommitsA git hosting platform

Self-hosted git. Push over HTTP or SSH, browse the code, open pull requests, review the diff, merge. Object storage holds the truth, local disk is a cache.
Repository listing. Directories first, last commit per row, branch switcher.

File view with syntax highlighting and a raw download.

Commit history for any branch.

Pull request list, filtered by state. Open count sits on the tab.

Pull request overview: markdown description, comments, live merge state. Author or anyone with write access can edit the title and description in place.

Split diff, computed from the merge base rather than the branch tips.

#123 cross references, search and filtersNot built yet: webhooks (in progress), Git LFS, CI.
| Layer | Choice |
|---|---|
| Web | Next.js 16, React 19, Tailwind, shadcn/ui |
| API | NestJS 12, OpenAPI client generated for the web |
| Database | Postgres, Drizzle |
| Storage | S3-compatible bucket (RustFS locally) |
| Search | Zoekt |
| Runtime | Bun, Turborepo workspace |
Needs Docker. The script asks for a domain (or IP), an SMTP server or email relay, and where to store data; it generates every secret you skip.
./docker/setup.sh # macOS / Linux
powershell -ExecutionPolicy Bypass -File docker\setup.ps1 # Windows
Full guide: apps/docs/content/docs/self-hosting.mdx.
Needs Bun and Docker.
docker compose up -d # Postgres, RustFS, and the ghost bucket
bun install
cp .env.example .env # set BETTER_AUTH_SECRET, the rest matches compose
bun run db:migrate
bun run dev
Web on http://localhost:3000, API on http://localhost:3001, RustFS console
on http://localhost:9001.
Push an existing repository. The password is a personal access token from account settings, not the login password.
git remote add origin http://localhost:3001/<username>/<repo>.git
git push -u origin main
For SSH, give the API a host key and add your public key under Settings → Security:
ssh-keygen -t ed25519 -N '' -f ghost_host_key
echo "GIT_SSH_HOST_KEY=$(base64 -i ghost_host_key)" >> .env
git remote set-url origin ssh://git@localhost:1031/<username>/<repo>.git
Without GIT_SSH_HOST_KEY the listener never starts and git speaks HTTP only.
apps/api NestJS API and the git HTTP transport
apps/web Next.js frontend
apps/docs Fumadocs user guide, e.g. how to sign commits (port 3003)
packages/db Drizzle schema and migrations
docker/ Self-hosting: compose file, Caddyfile, setup scripts
docs/ Design decisions, one file each
apps/docs is the guide for people using an instance: how to
generate an SSH key and connect with it, what the Verified badge on a commit
means, how to generate a GPG key, add it to an account, configure git to sign,
and what each failure message means. Run it
with bun run dev alongside everything else, or on its own:
bun run --filter @ghost/docs dev
docs/code-standards.md is the contract for contributions: DRY and SOLID, no DTO reshaping helpers, no concatenated strings, comments that explain why and fit on one line, and services/ holding nothing but services.
docs/ covers why the transport takes streams instead of
Request/Response, why a push is one compare-and-swap against a write-ahead
log, why materialization is forward-only replay, and why a pull request spans
two logs and lends objects instead of copying them. Each file lists what was
rejected and what it costs.