clone git clone git@git.botnet.pub:montana/openhub.git
files commits

readme

openhub

Minimal self-hosted git hosting with SSH key authentication. No passwords, no OAuth — just Ed25519 keys.

Features

  • SSH key auth — signup, login, and push all use your existing SSH key
  • Git over SSH and HTTPS — clone, fetch, and push with either protocol
  • Interactive SSH signupssh in with an unregistered key to create an account
  • SSH repo management — create, list, and delete repos over SSH
  • Web browsing — browse users, repos, file trees, file contents, and commit logs
  • Invite-only — signups require a single-use invite code
  • Quotas — per-user repo limits and per-repo disk limits via a pre-receive hook
  • Single binary — one Rust binary runs both the HTTP and SSH servers

Quick Start

Install the CLI

curl -fsSL https://your-host/install.sh | sh

This installs the openhub CLI, configures SSH (~/.ssh/config), and sets up the git credential helper.

Create an account

# Interactive signup over SSH (easiest)
ssh git@your-host

# Or via CLI
openhub register

Use it

openhub login
openhub repo new my-project
openhub clone you/my-project
cd my-project
# ... make changes ...
git push

SSH commands

# 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

Architecture

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!:

  • HTTP (default :8080) — API, git smart HTTP backend, web UI
  • SSH (default :22) — git transport, repo commands, interactive signup

Git 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.

Configuration

All config via environment variables:

VariableDefaultDescription
OPENHUB_SITE_NAMEopenhubSite name shown in UI and page titles
OPENHUB_BIND0.0.0.0:8080HTTP listen address
OPENHUB_SSH_BIND0.0.0.0:22SSH listen address
OPENHUB_REPOS_ROOT/srv/openhub/reposBare git repos directory
OPENHUB_DB_URLsqlite:/srv/openhub/openhub.dbSQLite database URL
OPENHUB_SSH_HOST_KEY/srv/openhub/ssh_host_ed25519_keySSH host key path (auto-generated)
OPENHUB_ADMIN_KEY(none)Bearer token for creating invites
OPENHUB_MAX_REPOS_PER_USER25Max repos per user
OPENHUB_MAX_REPO_BYTES52428800Max repo size in bytes (50 MiB)
OPENHUB_MAX_PUSH_BYTES10485760Max push request body (10 MiB)
OPENHUB_HOOK_PATH/usr/local/bin/git-quota-hookPath to pre-receive hook binary
OPENHUB_GIT_HTTP_BACKENDgit-http-backendPath to git HTTP backend

Deployment

Prerequisites

  • Rust toolchain
  • git, sqlite3, git-http-backend (from git-core)

Setup

# 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

docker compose up -d

Generate invites

curl -X POST https://your-host/api/admin/invites \
  -H "Authorization: Bearer $OPENHUB_ADMIN_KEY"

API

MethodPathAuthDescription
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/reposBearerCreate a repository
GET/api/repos/:user-List user's repositories
DELETE/api/repos/:user/:repoBearerDelete a repository
GET/api/stats-User/repo counts and recent repos
POST/api/admin/invitesAdminGenerate invite code

Building

# 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

License

MIT