A fast, self-hosted code forge written in Rust: Git hosting, code review, issues, CI/CD, a container registry and Pages in a single binary next to Postgres. Bring your existing pipelines and runners, import your projects, and keep your team's whole workflow on your own servers.
![]() Repository |
![]() Source file |
![]() Merge request |
![]() Code review |
![]() Pipeline |
![]() Job log |
![]() Issues |
![]() Security findings |
![]() Overview |
![]() Storage |
![]() Health |
git clone https://github.com/forgust-dev/forgust && cd forgust
# Your machine's address, not localhost: CI jobs run in containers and must reach it
export FORGUST_HOST=192.0.2.10
# Start Forgust with Postgres, S3 storage, a mail catcher and a runner
docker compose up -d --build
# Fill it with users, projects, merge requests and pipelines (prints the accounts)
python3 deploy/seed.pyThe app is available at http://$FORGUST_HOST:8080, and the emails it sends at http://$FORGUST_HOST:8027.
Run the published image (amd64 and arm64) next to Postgres, or build your own with
docker build -t forgust .:
services:
forgust:
image: ghcr.io/forgust-dev/forgust:0.1
restart: unless-stopped
read_only: true
tmpfs: [/tmp]
cap_drop: [ALL]
security_opt: ["no-new-privileges:true"]
ports: ["8080:8080", "2222:2222"]
environment:
FORGUST_DATABASE__URL: postgres://forgust:change-me@db:5432/forgust
FORGUST_SERVER__EXTERNAL_URL: https://git.example.com
FORGUST_SERVER__SSH_EXTERNAL: git.example.com:2222
volumes: [forgust-data:/var/lib/forgust]
depends_on:
db: { condition: service_healthy }
db:
image: postgres:17
restart: unless-stopped
environment: { POSTGRES_USER: forgust, POSTGRES_PASSWORD: change-me, POSTGRES_DB: forgust }
healthcheck: { test: ["CMD-SHELL", "pg_isready -U forgust"], interval: 5s }
volumes: [db-data:/var/lib/postgresql/data]
volumes: { forgust-data: {}, db-data: {} }- Verify the image: releases are signed and carry an SBOM, see SECURITY.md.
- First administrator: the log prints a one-time link on first start
(
docker compose logs forgust | grep setup). - Configuration: every key in
forgust.example.tomlcan be set asFORGUST_<SECTION>__<KEY>; OIDC providers go in[oidc.<name>]. - Backups:
forgust backup --output DIRandforgust restore --input DIRcover the database and the repositories. Also keep/var/lib/forgust/secret.key, the SSH host key next to it, and the S3 bucket if you use one.
- Git over HTTP and SSH, Git LFS with file locking
- Fast code browsing: tree, blame, history, compare, syntax highlighting
- Markdown with diagrams (Mermaid), math and alerts
- Edit files, create branches and tags from the browser
- Protected branches and tags, push rules, signed-commit verification (GPG and SSH)
- Releases with notes and attached files
- Merge requests with threaded line and multi-line comments
- Suggestions the author applies in one click
- Approvals,
CODEOWNERS, and merge checks (pipeline, approvals, threads, security) - Stacked merge requests, merge trains, auto-merge when every check passes
- Keyboard-driven review:
j/kto move,cto comment
- Issues with labels, milestones, due dates, assignees and templates
- Mentions,
#12and!45references, to-dos and a "Your work" inbox - Emoji reactions, watching projects, per-project notification levels, an inbox in the app (live), and a switch per kind of notification for the app and for email
- Pipelines with stages and
needsgraphs, live logs, artifacts, JUnit test reports - Runs on GitLab Runner (any executor; Docker is tested):
.gitlab-ci.ymlfiles work unchanged within a documented subset, and anything outside it fails with a clear error - Schedules, manual and delayed jobs, child pipelines,
resource_group,id_tokens - Environments and deployments, Pages, a built-in container registry
- Built-in dependency updates (Renovate), no bot account or token to set up
- Built-in scanners (code, secrets, dependencies, containers, infrastructure as code) with a Security tab, merge request checks and alerts
- OIDC sign-in, two-factor authentication, personal, project and deploy tokens
- Strict CSP, an image proxy for Markdown images, rate limits
- Overview with activity and CI statistics
- Users: block, reset two-factor, impersonate (audited)
- Storage by kind and by project, quotas per group and project
- Background jobs, health checks, backups from the UI, an instance banner
- Import from GitLab and GitHub: repositories, merge requests, issues, labels, members; a dry run first, resumable
- Webhooks, also formatted for Slack, Discord, Matrix, Mattermost and Teams
- A GitLab-compatible
/api/v4subset, so Renovate andglabwork - An MCP server for AI assistants, with OAuth sign-in
Measured on an 8-vCPU development machine, p95 with one client, release build:
| Repository tree, highlighted 2,000-line file, commit diff, blame | 7β11 ms |
| Merge request page and first diff page of a 1,000-file merge request | 9 ms |
ls-refs with a prefix on a repository with 1M refs |
13 ms |
| Pipeline created β job picked up by a runner | 24β40 ms |
Pushing one branch to a 1M-ref repository is the one speed target still missed (7 s against 300 ms).
Forgust is young (0.1) and built for private teams first. Not there yet: forks and merge requests from forks, wikis, snippets, package registries, push and pull mirroring, issue boards, confidential issues, code search (search covers titles), system hooks, and WebAuthn, SAML or LDAP sign-in.
| Layer | Technology |
|---|---|
| Backend | Rust + axum + tokio + sqlx |
| Git | git (writes and transfer) + gitoxide (hot reads), russh for SSH |
| Frontend | React 18 + TypeScript + Vite + TanStack Query |
| Database | PostgreSQL 17+ |
| Job queue | graphile_worker (on PostgreSQL) |
| Storage | Local disk or S3-compatible object storage |
docker compose -f compose.dev.yml up -d # Postgres :5440, S3 :9010, SMTP :1026 (inbox on :8026)
echo DATABASE_URL=postgres://forgust:forgust@localhost:5440/forgust > .env
cp forgust.example.toml forgust.toml # set database.url
(cd web && npm ci && npm run build) # or `npm run dev` with FORGUST_URL set
cargo run -p forgust-server -- serve # migrates on start
cargo test --workspace # one throwaway database per test
(cd web && npm run e2e) # end-to-end tests (Playwright)Contributions are welcome: see CONTRIBUTING.md (commits are signed off under the DCO). Report security problems privately, as SECURITY.md explains.
AI-assisted contributions are accepted, but must be disclosed on the PR. The same quality and security bar applies regardless of how the code was written.
MIT. GitLab is a trademark of GitLab Inc.; Forgust is not affiliated with GitLab.










