~gitpocket/gitpocket

1
c534f4e9e4f64f4e82a3b5ff40c84783059ea85d
mainfeed-discovery
gitpocket/README.md -rw-r--r--2.7 KiB ViewLogBlameView rawPermalink 7093e5fd3c feat(basin): minimal git host with ssh and smart https 1 months ago
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
forge is a small self hosted git server in Go modelled on the browsing side of sourcehut. It serves repositories over ssh and smart https, renders trees, blobs, logs, diffs, refs and READMEs as plain server side HTML with no JavaScript, and keeps users, keys, tokens and repository metadata in a single SQLite file.

## Build

```
CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o forge .
```

The SQLite driver is the pure Go modernc port, so the binary is static and copies to the server as one file next to a system `git`.

## Usage

```
forge -root /srv/forge serve -listen 127.0.0.1:3200 -host git.example.org
forge -root /srv/forge invite
```

The data directory holds `forge.db` and a `repos/<user>/<name>.git` tree of bare repositories. Registration needs a single use invite from the second command unless `serve` is given `-open`. Clone URLs take the sourcehut shape `https://host/~user/repo` and `git@host:~user/repo`, with the `.git` suffix optional.

Every read of git data shells out to the plumbing with a 30 second timeout rather than parsing packfiles in process. Tree listings use `ls-tree -l`, history uses `log` with a NUL separated format, and commit pages parse the unified output of `diff-tree -p --root -M` into hunks for rendering. This keeps the server stateless and lets large repositories inherit git's own performance, at the cost of one process spawn per page section.

## SSH

Pushes over ssh reuse the host sshd. Point `AuthorizedKeysCommand` for the `git` user at `forge -root /srv/forge keys %u %h %t %k`, which looks the presented key up by SHA256 fingerprint and answers with a forced command of `forge shell <user>`. That forced command reads `SSH_ORIGINAL_COMMAND`, checks ownership and visibility against the database, and execs `git upload-pack` or `git receive-pack` directly, so nothing stays resident between connections. The lookup opens the database read only and runs as root, while the forced command runs as the `git` user who owns the repositories.

## HTTPS

Anonymous clients may fetch public repositories. Private repositories and all pushes require basic auth with either the account password or an access token created in settings. Token hashes are stored as SHA256, passwords as bcrypt. The web forms rely on the standard library cross origin protection, so a POST without a same origin `Sec-Fetch-Site` or `Origin` header from a browser is refused while non browser git clients pass.

## Limitations

There is no syntax highlighting, no search, no per directory last commit column and no collaborators beyond the owner. Pull requests are planned as a second phase and the schema leaves room for them, but nothing is wired yet. Markdown READMEs are rendered with goldmark and sanitised with bluemonday, other README formats are shown preformatted.