README.md
Raw

Hearthforge

A self-hosted git forge designed to host your own repositories, but allow others to interact with them via issues and patch proposals. Frontend works without any JS at all enabled, just required for WebAuthn (with graceful fallback to password-only).

Features

  • Repository browser — file tree, directly edit single files, blob view, commit log, markdown rendering, media previews
  • Issues — create, comment, react
  • Patches — submit git .patch files for review & comments. Admin can merge applicable patches directly into the repository.
  • Templates — issue/patch templates
  • Releases — releases with source archives, extra uploaded assets, and optional tag creation
  • SSH push/pull — built-in SSH server, no external git daemon needed
  • Auth — password login or passkeys (WebAuthn/FIDO2)
  • Commit signing — merged patches and filed edited through the UI are automatically signed and verification badges are shown in the commit list view
  • Optional registration — others can create accounts to file issues and patches; can be disabled, or put in queue mode where the admin manually approves new accounts.

Stack

  • Bun — runtime and package manager
  • ElysiaJS — HTTP framework
  • SQLite — single-file database via Kysely
  • Server-side JSX via @kitajs/html (no client-side framework)
  • Shiki — syntax highlighting

Running

bun install
bun run db:init   # creates database and admin account
bun run start     # http://localhost:3000, SSH on port 2222

Default admin credentials: admin / changeme

Manual repository interactions

Existing Repositories can be copied manually to the data/repos directory. Non-bare repos are automatically converted to bare repos on startup, discarding uncomitted changes and worktrees. Pushing directly to the repositories (i.e. not through the bundled http/ssh endpoints) should generally works as well.

Docker / Podman

Container image and compose file are provided.

docker compose up # or
podman compose up

Configuration

All settings are environment variables:

Variable Default Description
PORT 3000 HTTP port
SSH_PORT 2222 SSH port
DATA_DIR ./data Repos, database, uploads
ADMIN_PASSWORD changeme Initial admin password
OWNER_DISPLAY_NAME Admin Display name for the owner
BASE_URL http://localhost:3000 Used in clone URLs and links
REGISTRATION_TYPE enabled Registration mode: enabled, disabled, or queue (requires admin approval)
REGISTER_QUESTION (empty) Question shown on the registration form when REGISTRATION_TYPE=queue
MAX_UPLOAD_BYTES 10485760 Max request body size (any uploads/requests)
MAX_USER_UPLOAD_BYTES 2097152 Max request body size (user uploads)
INLINE_MAX_BYTES 524288 Max file size to render inline in the file view
SSH_DISABLED 0 Disable the embedded SSH-server
TRUSTED_PROXY 0 Trust X-Forwarded-For
RATE_LIMIT_DISABLED 0 Set to 1 to disable rate limiting
HIGHLIGHT_WORKERS 4 Number of syntax highlighting workers*
COMMITTER_NAME $OWNER_DISPLAY_NAME Git committer name used when merging patches or editing files through the UI
COMMITTER_EMAIL $OWNER_DISPLAY_NAME@<hostname> same as above but for email

* More workers mean more CPU cores can be used to parallelize highlighting of files. Because of the language grammars, which can't be shared across workers, the memory usage per worker is quite high, at about 200MB. So be careful when increasing this.

SSH access

Add your public key under Settings → SSH keys, then clone with:

git clone ssh://git@localhost:{SSH_PORT}/{REPO_NAME}

Pushing is also supported for the admin.

Development

bun run dev           # watch mode
bun run lint          # Biome lint
bun run format        # Biome format
bun run test          # Run E2E and unit tests (don't use bun test directly, it doesn't respect the timeout)

Roadmap

  • Use git-bug for issue tracking instead of custom implementation
  • more repository manipulation through the UI, e.g. file/directory/branch creation, renaming and deletion