rabun-git architecture
How the forge is put together (layout, ACL, systemd).
How the forge is put together (layout, ACL, systemd). For a beginner walkthrough with examples, start at the user guide.
Self-hosted git forge CLI. Burton and Rabun do not import this crate. Warehouse workers remain the writers of warehouse trees; this process is a git remote they may push to.
This machine Your server
git clone/push --SSH:2222--> rabun-git serve (russh)
ssh git@host request … ----> same binary, management commands
bare repos under RABUN_GIT_ROOT/repos/
users.yaml, keys/, access.yaml
refs/rabun/requests/*
.rabun/workflows runner
SSH is the only public network surface (default 0.0.0.0:2222; russh username git). Loopback GET /health is companion heartbeat only (127.0.0.1:8792). There is no HTTP git UI on serve. On this machine, rgit view can render a local tree with Zola on loopback. The systemd user is rabun-git; admin SSH on port 22 is unchanged.
Layout
$RABUN_GIT_ROOT/ (default data/git):
users.yaml— login + forge admin flagkeys/<user>.pub— OpenSSH public keysaccess.yaml—owner/name→ user →read|write|adminrepos/<owner>/<name>.git/— bare repositoriesruns/<owner>/<name>/<run-id>/—status.yaml+job.yaml+log.txtbuilders.yaml— registered workflow agents and labelsssh_host_ed25519_key— generated on firstservestatus.json—rabun.companion/v1
ACL
- Forge admin (
users.yaml) bypasses per-repo ACL. - Local CLI (
rabun-giton the host) is the operator and has full access. - SSH identity is the key. Username
gitmaps to the key's owner (GitHub-style). read: fetch, list requests/runs.write: push non-protected branches, open/review requests.admin(repo or forge): pushmaster/main, merge, grant access.hooks/updaterejects protected-branch updates for non-admins. Env:RABUN_GIT_USER,RABUN_GIT_REPO,RABUN_GIT_ROOT,RABUN_GIT_BIN. If the new tip contains.rabun/version.tomlwithenforceflags, it also rejects non-conventional commits and non-SemVer tags. Set those flags tofalseto disable (see versioning).
Merge requests
Stored in git so they clone with the repo:
refs/rabun/requests/<id>/headrefs/rabun/requests/<id>/baserefs/rabun/requests/<id>/meta— YAML blob (title, author, state, reviews)
git push origin HEAD:refs/rabun/requests/new/<branch> allocates the next id after receive-pack. Merge is fast-forward only in v1.
Workflows
.rabun/workflows/*.yml at the triggering commit. Subset: on.push.branches, on.tag, on.request, jobs.*.steps[].run, jobs.*.runs-on, jobs.*.shell, env, timeout_minutes. No uses:, full matrix, or containers. Empty runs-on (or linux with no linux builder) runs on the forge host. Other labels are queued in runs/ until a registered agent claims them over SSH (builders.yaml).
systemd
Pack this checkout and copy it onto Ubuntu over SSH (same flow as Burton and Rabun): deploy Ubuntu. The unit shipped in deploy/ubuntu/rabun-git.service runs as user rabun-git with forge data under /var/lib/rabun-git. Git clients still use ssh://git@HOST:2222/….
[Unit]
Description=Rabun git forge
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=rabun-git
Group=rabun-git
WorkingDirectory=/var/lib/rabun-git
Environment=RABUN_GIT_CONFIG=/etc/rabun-git/rabun-git.toml
Environment=RABUN_GIT_ROOT=/var/lib/rabun-git
EnvironmentFile=-/etc/rabun-git/rabun-git.env
ExecStart=/usr/local/bin/rabun-git serve
Restart=on-failure
Optional companion rabun.toml on the host (register-app.sh upserts this on install):
[[apps]]
name = "git"
description = "Rabun git forge"
command = "rabun-git"
args = ["serve"]
health_url = "http://127.0.0.1:8792/health"
status_file = "/var/lib/rabun-git/status.json"
Settings stay in /etc/rabun-git/rabun-git.env, not /etc/rabun/rabun.env.
Privacy
No telemetry and no outbound forge calls. Host keys and user keys stay on disk you own. Companion JSON never includes key material.