# Hearthforge ![](public/assets/favicon.svg)
![](preview.png)

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, README 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 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

## Stack

- [Bun](https://bun.sh) — runtime and package manager
- [ElysiaJS](https://elysiajs.com) — HTTP framework
- SQLite — single-file database via Kysely
- Server-side JSX via @kitajs/html (no client-side framework)
- Shiki — syntax highlighting

## Running

```bash
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 creation

Repositories can bei either created through the UI, or existing ones 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.

### Docker / Podman
Container images are provided.
```bash
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_DISABLED` | `0`                              | Set to `1` to disable signups                   |
| `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    |
| `COMMITTER_EMAIL`       | `$OWNER_DISPLAY_NAME@<hostname>` | Git committer email used when merging patches   |

\* 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

```bash
bun run dev           # watch mode
bun run lint          # Biome lint
bun run format        # Biome format
bun run test          # Playwright E2E tests (don't use bun test, it doesn't respect the timeout)
```

## Roadmap
- Use [git-bug](https://github.com/git-bug/git-bug) for issue tracking instead of custom implementation
- Issue labels
- redirect image urls in readme
- registration queue
- edit patches
- show ^M in diffs