git clone git@git.botnet.pub:montana/openhub.git
Minimal self-hosted git hosting with SSH key authentication. No passwords, no OAuth — just Ed25519 keys.
ssh in with an unregistered key to create an accountcurl -fsSL https://your-host/install.sh | sh
This installs the openhub CLI, configures SSH (~/.ssh/config), and sets up the git credential helper.
# Interactive signup over SSH (easiest)
ssh git@your-host
# Or via CLI
openhub register
openhub login
openhub repo new my-project
openhub clone you/my-project
cd my-project
# ... make changes ...
git push
# Clone over SSH
git clone git@your-host:user/repo.git
# Manage repos
ssh git@your-host repo new my-project
ssh git@your-host repo list
ssh git@your-host repo delete my-project
server/ Axum HTTP server + russh SSH server
cli/ openhub CLI (register, login, repo management, clone)
hook/ git pre-receive hook for repo size enforcement
scripts/ install.sh, git-credential-openhub
migrations/ SQLite schema
deploy/ systemd unit, setup script
The server runs two listeners via tokio::select!:
:8080) — API, git smart HTTP backend, web UI:22) — git transport, repo commands, interactive signupGit protocol is handled by the system git-http-backend (HTTP) and git-upload-pack/git-receive-pack (SSH). The Rust server handles auth, routing, and quotas.
All config via environment variables:
| Variable | Default | Description |
|---|---|---|
OPENHUB_SITE_NAME | openhub | Site name shown in UI and page titles |
OPENHUB_BIND | 0.0.0.0:8080 | HTTP listen address |
OPENHUB_SSH_BIND | 0.0.0.0:22 | SSH listen address |
OPENHUB_REPOS_ROOT | /srv/openhub/repos | Bare git repos directory |
OPENHUB_DB_URL | sqlite:/srv/openhub/openhub.db | SQLite database URL |
OPENHUB_SSH_HOST_KEY | /srv/openhub/ssh_host_ed25519_key | SSH host key path (auto-generated) |
OPENHUB_ADMIN_KEY | (none) | Bearer token for creating invites |
OPENHUB_MAX_REPOS_PER_USER | 25 | Max repos per user |
OPENHUB_MAX_REPO_BYTES | 52428800 | Max repo size in bytes (50 MiB) |
OPENHUB_MAX_PUSH_BYTES | 10485760 | Max push request body (10 MiB) |
OPENHUB_HOOK_PATH | /usr/local/bin/git-quota-hook | Path to pre-receive hook binary |
OPENHUB_GIT_HTTP_BACKEND | git-http-backend | Path to git HTTP backend |
git, sqlite3, git-http-backend (from git-core)# Run the setup script (creates user, disk image, builds, installs)
sudo deploy/setup.sh
# Create an admin key for generating invites
echo 'OPENHUB_ADMIN_KEY=your-secret-key' >> /srv/openhub/openhub.env
# Start
sudo systemctl start openhub
docker compose up -d
curl -X POST https://your-host/api/admin/invites \
-H "Authorization: Bearer $OPENHUB_ADMIN_KEY"
| Method | Path | Auth | Description |
|---|---|---|---|
POST | /api/signup | - | Create account with SSH key + invite |
POST | /api/login/challenge | - | Request login challenge nonce |
POST | /api/login/verify | - | Verify signature, get bearer token |
POST | /api/repos | Bearer | Create a repository |
GET | /api/repos/:user | - | List user's repositories |
DELETE | /api/repos/:user/:repo | Bearer | Delete a repository |
GET | /api/stats | - | User/repo counts and recent repos |
POST | /api/admin/invites | Admin | Generate invite code |
# SQLite DB needed for sqlx compile-time checks
sqlite3 /tmp/openhub_build.db < migrations/0001_init.sql
DATABASE_URL=sqlite:/tmp/openhub_build.db cargo build --release
MIT