Blazing fast, self hosted Git hosting in Rust. One binary, no external services.
See the code
Blazing fast, self-hosted Git — written in Rust, shipped as one binary, with no external services.
rbit gives you repositories, issues, pull requests, reviews and CI checks on your own server, and it is built around three things: speed, security and performance. No Postgres, no Redis, no JavaScript runtime — download it, run it, push.
Quick start · Why rbit · Features · Install · First steps · Configuration · Command line · Development · Community
docker run -d --name rbit -p 3000:3000 -v rbit-data:/data ghcr.io/gitrbit/rbit:latest
Open http://localhost:3000 and sign up — the first account becomes the site administrator. Create a repository (or import one from GitHub or Gitea), then push:
git remote add rbit http://localhost:3000/<you>/<repo>.git
git push rbit main
No Docker? Download a release binary and run ./rbit serve, or build
from source. For a production server, follow docs/deployment.md.
Git and code
git-lfs-authenticate over SSH; objects are stored
once and shared by forks; the browser shows the stored file, not the pointer..zip/.tar.gz archives, blame, compare, forks,
pull and push mirrors, README relative links and images.Collaboration
#12 / @name references, fixes #12 in commits, search with
GitHub-style filters, and a notification inbox — by email too if you want it, threaded per issue, with
one-click unsubscribe.Automation and integrations
/api/v1, OpenAPI 3.1: repositories, issues, pull requests,
collaborators, teams, releases with file uploads, forks, statuses, …) and HMAC-signed, GitHub-shaped webhooks
(push, issues, pull requests, reviews, releases, collaborators, statuses, …) with a persistent, retrying
delivery queue.Running it
See docs/deployment.md for running it in production, docs/ARCHITECTURE.md for the design, ROADMAP.md for what comes next, and docs/HANDOFF.md for the project's current state.
rbit needs Git on the server at run time (the transports, git gc and backups use the
git executable). Everything else is inside the binary: templates, styles, scripts and the
database migrations.
Every release has archives for Linux (x86_64 and
aarch64, glibc 2.35 or newer), macOS (Intel and Apple silicon) and Windows (x86_64, .zip), plus a
SHA256SUMS file. Each archive holds the rbit binary, the licenses, this README, the
changelog, the third-party notices, the example configuration and the systemd unit.
version=0.1.0 # the release you want
target=x86_64-unknown-linux-gnu # or aarch64-unknown-linux-gnu, aarch64-apple-darwin, ...
curl -LO "https://github.com/GitRbit/rbit/releases/download/v$version/rbit-$version-$target.tar.gz"
curl -LO "https://github.com/GitRbit/rbit/releases/download/v$version/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS # macOS: shasum -a 256 --check --ignore-missing
tar -xzf "rbit-$version-$target.tar.gz"
./rbit-$version-$target/rbit serve # http://localhost:3000, data in ./data
For a real server (a system user, TLS in front, systemd, backups) follow docs/deployment.md.
Multi-architecture images (linux/amd64, linux/arm64) are published to the GitHub
Container Registry for every release, tagged with the version (0.1.0, 0.1) and latest:
docker run -d --name rbit -p 3000:3000 -v rbit-data:/data \
-e RBIT_SERVER__PUBLIC_URL=https://git.example.com \
ghcr.io/gitrbit/rbit:latest
The image runs as an unprivileged user, keeps everything under /data, and has a health
check on /healthz. Add -p 2222:2222 -e RBIT_SSH__ENABLED=true for Git over SSH.
Requirements: Rust 1.94+, Git, and Node.js (build-time only, for Tailwind CSS).
npm ci
npm run build # vendors htmx and builds the stylesheet
cargo run # serves http://localhost:3000, data in ./data
cargo build --release produces target/release/rbit; docker build -t rbit . builds the
image from source.
The first account you create becomes the site administrator.
Clone and push over HTTPS with your username and password:
git clone http://localhost:3000/<owner>/<repo>.git
Instead of your account password you can use a personal access token (rbit_…) as the Git
password — required once two-factor authentication is enabled. Tokens are scoped (read
can clone and fetch, write can also push, admin can also change repository settings,
webhooks and delete through the API), can expire, and can be revoked individually. Tokens
issued by earlier releases start with rit_… and keep working.
With [ssh] enabled = true, add a public key under Settings → SSH keys and use the SSH
URL from the repository's Clone menu.
Git LFS needs no setup: git lfs track and push as usual, over
HTTPS or SSH, with the same credentials.
The same tokens authenticate the REST API:
curl -H "Authorization: Bearer rbit_…" http://localhost:3000/api/v1/user
GET /api/v1/openapi.json describes every endpoint.
Administrators can personalize a self-hosted instance in Site administration → Settings:
name, logo, favicon, app icon, primary button colors, site description, welcome copy, footer,
support/terms/privacy links, attribution, version visibility and welcome-page features.
Registration, organization creation and default repository visibility are also editable there.
These settings are validated, audited, stored in SQLite and apply immediately. Use HTTPS image
URLs or local /paths served by your reverse proxy; no asset rebuild is required.
Site administration → Configuration organizes deployment settings into labeled forms for SMTP, SSH, security, SSO, integrations and feature limits. Each section has help text, toggles, dropdowns and numeric limits. Save individual sections, then restart the server. Identity providers have add/remove cards; add the providers first, then enter credentials and save. No JSON editing or JavaScript is required.
Credential inputs are always empty: leave them blank to preserve existing secrets, enter a replacement, or explicitly select Clear. Validation errors retain ordinary input, while new credentials must be entered again. Protect the instance database and its backups, which contain these credentials. Storage relocation requires an offline move and a file/environment change.
Precedence is defaults → TOML → saved administrator deployment settings → legacy RUSTIT_* →
RBIT_*. Live branding and policy overrides take precedence over their deployment defaults.
Remove saved deployment overrides in the configuration screen to return to file/environment
configuration on restart. For recovery, start with RBIT_IGNORE_ADMIN_CONFIG=1, correct or remove
the saved overrides, then remove that environment variable and restart.
Settings come from built-in defaults, then an optional TOML file (--config rbit.toml),
then RBIT_* environment variables (nested keys use __, e.g.
RBIT_SERVER__PUBLIC_URL). Every key is optional. A fully commented production example
lives in deploy/rbit.example.toml.
| Section | Purpose | Key settings |
|---|---|---|
[server] | HTTP listener and identity | bind, public_url, site_name, open_registration (default for the runtime setting) |
[storage] | Data location | data_dir (SQLite, redb, repositories, release files, LFS objects) |
[security] | Sessions and abuse protection | session_lifetime_days, min_password_length, trusted_proxies (CIDRs allowed to set X-Forwarded-*), rate_limit |
[repository] | Git behaviour | default_branch, git_binary, max_render_bytes |
[mail] | Outgoing email | transport = disabled | log | smtp; from_address, from_name, smtp_host, smtp_port, smtp_security (starttls | tls | none), smtp_username, smtp_password, timeout_seconds |
[ssh] | Built-in SSH server | enabled, bind, public_host, public_port, host_key_path, connection limits and timeouts |
[operations] | Maintenance and metrics | metrics, metrics_token, warm_caches_on_push, maintenance_interval_minutes, job_concurrency, insights cache limits |
[api] | REST API | enabled, default_page_size, max_page_size |
[webhooks] | Outgoing deliveries | enabled, allow_private_addresses, timeout_seconds, max_attempts, concurrency, delivery_retention_days |
[releases] | Release files (web and API uploads) | max_asset_bytes, max_assets_per_release, upload_timeout_seconds |
[mirrors] | Pull mirrors | enabled, default_interval_minutes, min_interval_minutes, fetch_timeout_seconds, allow_private_addresses |
[push_mirrors] | Push mirrors | enabled, interval_minutes, debounce_seconds, push_timeout_seconds, allow_private_addresses, allow_local_urls |
[imports] | Importing from GitHub and Gitea/Forgejo | enabled, max_concurrent, git_timeout_seconds, api_timeout_seconds, rate_limit_max_wait_seconds, author_mapping (none | email | email_or_username), allow_private_addresses |
[issues] | Issues and notifications | scan_commit_limit, notifications, notification_retention_days |
[pulls] | Pull requests | merge_timeout_seconds, max_concurrent_merges, mergeability_concurrency, max_commits, noreply_domain |
[notifications] | Email notifications on top of the inbox (need a [mail] transport and a verified address) | email, default_email (off | participating | all) |
[editor] | Editing and uploading files in the browser | max_upload_bytes, max_upload_files, upload_timeout_seconds |
[lfs] | Git Large File Storage | enabled, max_object_bytes, token_lifetime_seconds |
[auth] | External sign-in; register {public_url}/login/{id}/callback at the provider | timeout_seconds, allow_private_addresses, [[auth.providers]] (kind = oidc | github, id, name, issuer / base_url, client_id, client_secret, scopes, allow_registration, trust_email, trust_mfa) |
Site name, registration, who may create organisations and the default repository visibility can also be changed at runtime by administrators under Site administration → Settings.
| Command | Purpose |
|---|---|
rbit serve | Run the web (and SSH, if enabled) server — the default |
rbit migrate | Apply database migrations and exit |
rbit backup --output DIR | Write a consistent backup (database snapshot, repository mirrors, release files, LFS objects, manifest) |
rbit user create <name> <email> [--admin] | Create an account (password read from stdin) |
Every command accepts -c, --config <FILE> (or RBIT_CONFIG); rbit --version prints the version.
Log verbosity follows RUST_LOG (e.g. RUST_LOG=debug), and NO_COLOR turns off coloured logs.
CONTRIBUTING.md explains the setup, the live development server
(npm run dev), the quality gate and the rules for commits and pull requests. In short:
npm run dev # rebuild and restart on every change, data in ./data-live
cargo fmt --all --check # rustfmt.toml pins the style
cargo clippy --workspace --all-targets -- -D warnings # pedantic lints, workspace-wide
cargo test --workspace # unit, integration, property and end-to-end tests
The end-to-end suite (crates/rbit-e2e) boots real servers on ephemeral ports and drives
them with an HTTP client and the git CLI; the SSH tests also need the OpenSSH client.
The orange frog is rbit's logo and mascot. The original artwork lives in
crates/rbit-web/assets/logo.png and is shared by
the README and landing page. After replacing it, run npm run icons to regenerate
the browser, home-screen, and installable-app icons, and commit the generated PNGs.
| Crate | Responsibility |
|---|---|
rbit-core | Domain types, validated names, permissions, configuration |
rbit-storage | SQLite (sqlx) and redb persistence |
rbit-auth | Password hashing, session and token secrets, TOTP, passkeys (WebAuthn), OpenID Connect token checks, access policy |
rbit-git | Repository storage, read model, diffs, blame, compare, archives, forks, mirrors, languages, maintenance (gitoxide) |
rbit-transport | Git smart protocol: stateless (HTTP) and interactive (SSH) modes |
rbit-services | Application use-cases, domain events, background jobs, webhook delivery, imports |
rbit-mail | Email rendering and delivery (SMTP, log) |
rbit-ssh | Built-in SSH server for Git over SSH |
rbit-web | Routes, REST API, templates, themes, assets, metrics |
rbit-server | The rbit binary: CLI, configuration, backups |
rbit-e2e | End-to-end and Git compatibility tests (test-only) |
rbit is licensed under either of
at your option. Bundled third-party material (htmx, the tinted-theming schemes, ...) keeps its own license; see THIRD-PARTY.md.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in rbit by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
Blazing fast, self hosted Git hosting in Rust. One binary, no external services.
See the code
Blazing fast, self-hosted Git — written in Rust, shipped as one binary, with no external services.
rbit gives you repositories, issues, pull requests, reviews and CI checks on your own server, and it is built around three things: speed, security and performance. No Postgres, no Redis, no JavaScript runtime — download it, run it, push.
Quick start · Why rbit · Features · Install · First steps · Configuration · Command line · Development · Community
docker run -d --name rbit -p 3000:3000 -v rbit-data:/data ghcr.io/gitrbit/rbit:latest
Open http://localhost:3000 and sign up — the first account becomes the site administrator. Create a repository (or import one from GitHub or Gitea), then push:
git remote add rbit http://localhost:3000/<you>/<repo>.git
git push rbit main
No Docker? Download a release binary and run ./rbit serve, or build
from source. For a production server, follow docs/deployment.md.
Git and code
git-lfs-authenticate over SSH; objects are stored
once and shared by forks; the browser shows the stored file, not the pointer..zip/.tar.gz archives, blame, compare, forks,
pull and push mirrors, README relative links and images.Collaboration
#12 / @name references, fixes #12 in commits, search with
GitHub-style filters, and a notification inbox — by email too if you want it, threaded per issue, with
one-click unsubscribe.Automation and integrations
/api/v1, OpenAPI 3.1: repositories, issues, pull requests,
collaborators, teams, releases with file uploads, forks, statuses, …) and HMAC-signed, GitHub-shaped webhooks
(push, issues, pull requests, reviews, releases, collaborators, statuses, …) with a persistent, retrying
delivery queue.Running it
See docs/deployment.md for running it in production, docs/ARCHITECTURE.md for the design, ROADMAP.md for what comes next, and docs/HANDOFF.md for the project's current state.
rbit needs Git on the server at run time (the transports, git gc and backups use the
git executable). Everything else is inside the binary: templates, styles, scripts and the
database migrations.
Every release has archives for Linux (x86_64 and
aarch64, glibc 2.35 or newer), macOS (Intel and Apple silicon) and Windows (x86_64, .zip), plus a
SHA256SUMS file. Each archive holds the rbit binary, the licenses, this README, the
changelog, the third-party notices, the example configuration and the systemd unit.
version=0.1.0 # the release you want
target=x86_64-unknown-linux-gnu # or aarch64-unknown-linux-gnu, aarch64-apple-darwin, ...
curl -LO "https://github.com/GitRbit/rbit/releases/download/v$version/rbit-$version-$target.tar.gz"
curl -LO "https://github.com/GitRbit/rbit/releases/download/v$version/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS # macOS: shasum -a 256 --check --ignore-missing
tar -xzf "rbit-$version-$target.tar.gz"
./rbit-$version-$target/rbit serve # http://localhost:3000, data in ./data
For a real server (a system user, TLS in front, systemd, backups) follow docs/deployment.md.
Multi-architecture images (linux/amd64, linux/arm64) are published to the GitHub
Container Registry for every release, tagged with the version (0.1.0, 0.1) and latest:
docker run -d --name rbit -p 3000:3000 -v rbit-data:/data \
-e RBIT_SERVER__PUBLIC_URL=https://git.example.com \
ghcr.io/gitrbit/rbit:latest
The image runs as an unprivileged user, keeps everything under /data, and has a health
check on /healthz. Add -p 2222:2222 -e RBIT_SSH__ENABLED=true for Git over SSH.
Requirements: Rust 1.94+, Git, and Node.js (build-time only, for Tailwind CSS).
npm ci
npm run build # vendors htmx and builds the stylesheet
cargo run # serves http://localhost:3000, data in ./data
cargo build --release produces target/release/rbit; docker build -t rbit . builds the
image from source.
The first account you create becomes the site administrator.
Clone and push over HTTPS with your username and password:
git clone http://localhost:3000/<owner>/<repo>.git
Instead of your account password you can use a personal access token (rbit_…) as the Git
password — required once two-factor authentication is enabled. Tokens are scoped (read
can clone and fetch, write can also push, admin can also change repository settings,
webhooks and delete through the API), can expire, and can be revoked individually. Tokens
issued by earlier releases start with rit_… and keep working.
With [ssh] enabled = true, add a public key under Settings → SSH keys and use the SSH
URL from the repository's Clone menu.
Git LFS needs no setup: git lfs track and push as usual, over
HTTPS or SSH, with the same credentials.
The same tokens authenticate the REST API:
curl -H "Authorization: Bearer rbit_…" http://localhost:3000/api/v1/user
GET /api/v1/openapi.json describes every endpoint.
Administrators can personalize a self-hosted instance in Site administration → Settings:
name, logo, favicon, app icon, primary button colors, site description, welcome copy, footer,
support/terms/privacy links, attribution, version visibility and welcome-page features.
Registration, organization creation and default repository visibility are also editable there.
These settings are validated, audited, stored in SQLite and apply immediately. Use HTTPS image
URLs or local /paths served by your reverse proxy; no asset rebuild is required.
Site administration → Configuration organizes deployment settings into labeled forms for SMTP, SSH, security, SSO, integrations and feature limits. Each section has help text, toggles, dropdowns and numeric limits. Save individual sections, then restart the server. Identity providers have add/remove cards; add the providers first, then enter credentials and save. No JSON editing or JavaScript is required.
Credential inputs are always empty: leave them blank to preserve existing secrets, enter a replacement, or explicitly select Clear. Validation errors retain ordinary input, while new credentials must be entered again. Protect the instance database and its backups, which contain these credentials. Storage relocation requires an offline move and a file/environment change.
Precedence is defaults → TOML → saved administrator deployment settings → legacy RUSTIT_* →
RBIT_*. Live branding and policy overrides take precedence over their deployment defaults.
Remove saved deployment overrides in the configuration screen to return to file/environment
configuration on restart. For recovery, start with RBIT_IGNORE_ADMIN_CONFIG=1, correct or remove
the saved overrides, then remove that environment variable and restart.
Settings come from built-in defaults, then an optional TOML file (--config rbit.toml),
then RBIT_* environment variables (nested keys use __, e.g.
RBIT_SERVER__PUBLIC_URL). Every key is optional. A fully commented production example
lives in deploy/rbit.example.toml.
| Section | Purpose | Key settings |
|---|---|---|
[server] | HTTP listener and identity | bind, public_url, site_name, open_registration (default for the runtime setting) |
[storage] | Data location | data_dir (SQLite, redb, repositories, release files, LFS objects) |
[security] | Sessions and abuse protection | session_lifetime_days, min_password_length, trusted_proxies (CIDRs allowed to set X-Forwarded-*), rate_limit |
[repository] | Git behaviour | default_branch, git_binary, max_render_bytes |
[mail] | Outgoing email | transport = disabled | log | smtp; from_address, from_name, smtp_host, smtp_port, smtp_security (starttls | tls | none), smtp_username, smtp_password, timeout_seconds |
[ssh] | Built-in SSH server | enabled, bind, public_host, public_port, host_key_path, connection limits and timeouts |
[operations] | Maintenance and metrics | metrics, metrics_token, warm_caches_on_push, maintenance_interval_minutes, job_concurrency, insights cache limits |
[api] | REST API | enabled, default_page_size, max_page_size |
[webhooks] | Outgoing deliveries | enabled, allow_private_addresses, timeout_seconds, max_attempts, concurrency, delivery_retention_days |
[releases] | Release files (web and API uploads) | max_asset_bytes, max_assets_per_release, upload_timeout_seconds |
[mirrors] | Pull mirrors | enabled, default_interval_minutes, min_interval_minutes, fetch_timeout_seconds, allow_private_addresses |
[push_mirrors] | Push mirrors | enabled, interval_minutes, debounce_seconds, push_timeout_seconds, allow_private_addresses, allow_local_urls |
[imports] | Importing from GitHub and Gitea/Forgejo | enabled, max_concurrent, git_timeout_seconds, api_timeout_seconds, rate_limit_max_wait_seconds, author_mapping (none | email | email_or_username), allow_private_addresses |
[issues] | Issues and notifications | scan_commit_limit, notifications, notification_retention_days |
[pulls] | Pull requests | merge_timeout_seconds, max_concurrent_merges, mergeability_concurrency, max_commits, noreply_domain |
[notifications] | Email notifications on top of the inbox (need a [mail] transport and a verified address) | email, default_email (off | participating | all) |
[editor] | Editing and uploading files in the browser | max_upload_bytes, max_upload_files, upload_timeout_seconds |
[lfs] | Git Large File Storage | enabled, max_object_bytes, token_lifetime_seconds |
[auth] | External sign-in; register {public_url}/login/{id}/callback at the provider | timeout_seconds, allow_private_addresses, [[auth.providers]] (kind = oidc | github, id, name, issuer / base_url, client_id, client_secret, scopes, allow_registration, trust_email, trust_mfa) |
Site name, registration, who may create organisations and the default repository visibility can also be changed at runtime by administrators under Site administration → Settings.
| Command | Purpose |
|---|---|
rbit serve | Run the web (and SSH, if enabled) server — the default |
rbit migrate | Apply database migrations and exit |
rbit backup --output DIR | Write a consistent backup (database snapshot, repository mirrors, release files, LFS objects, manifest) |
rbit user create <name> <email> [--admin] | Create an account (password read from stdin) |
Every command accepts -c, --config <FILE> (or RBIT_CONFIG); rbit --version prints the version.
Log verbosity follows RUST_LOG (e.g. RUST_LOG=debug), and NO_COLOR turns off coloured logs.
CONTRIBUTING.md explains the setup, the live development server
(npm run dev), the quality gate and the rules for commits and pull requests. In short:
npm run dev # rebuild and restart on every change, data in ./data-live
cargo fmt --all --check # rustfmt.toml pins the style
cargo clippy --workspace --all-targets -- -D warnings # pedantic lints, workspace-wide
cargo test --workspace # unit, integration, property and end-to-end tests
The end-to-end suite (crates/rbit-e2e) boots real servers on ephemeral ports and drives
them with an HTTP client and the git CLI; the SSH tests also need the OpenSSH client.
The orange frog is rbit's logo and mascot. The original artwork lives in
crates/rbit-web/assets/logo.png and is shared by
the README and landing page. After replacing it, run npm run icons to regenerate
the browser, home-screen, and installable-app icons, and commit the generated PNGs.
| Crate | Responsibility |
|---|---|
rbit-core | Domain types, validated names, permissions, configuration |
rbit-storage | SQLite (sqlx) and redb persistence |
rbit-auth | Password hashing, session and token secrets, TOTP, passkeys (WebAuthn), OpenID Connect token checks, access policy |
rbit-git | Repository storage, read model, diffs, blame, compare, archives, forks, mirrors, languages, maintenance (gitoxide) |
rbit-transport | Git smart protocol: stateless (HTTP) and interactive (SSH) modes |
rbit-services | Application use-cases, domain events, background jobs, webhook delivery, imports |
rbit-mail | Email rendering and delivery (SMTP, log) |
rbit-ssh | Built-in SSH server for Git over SSH |
rbit-web | Routes, REST API, templates, themes, assets, metrics |
rbit-server | The rbit binary: CLI, configuration, backups |
rbit-e2e | End-to-end and Git compatibility tests (test-only) |
rbit is licensed under either of
at your option. Bundled third-party material (htmx, the tinted-theming schemes, ...) keeps its own license; see THIRD-PARTY.md.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in rbit by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.