# otgit

Self-hosted git host with a 1999 Microsoft-era UI. Reuses Octuna's CSS shell.

![otgit](public/logo.png)

## What it does

- Host git repositories on your own server
- Browse repos, files, commits, and diffs in the browser
- Push and pull over HTTPS smart protocol with basic auth
- Render Markdown READMEs (safe subset, no raw HTML)
- Render unified diffs with red/green hunks like GitHub
- Per-user accounts, public/private repos, admin web UI

## Why

Modern feature set, retro skin. Lightweight, low RAM, low code, secure.
No framework, no database, two npm dependencies maximum (currently zero
runtime deps beyond Node itself). Designed to be portable, easy to read,
and easy to host on any small VPS that has Node and the `git` binary.

## Hard limits

- Server target under 60 MB resident, capped at 64 MB heap
- No source file over 400 lines
- Total CSS under 1000 lines
- Every tunable comes from `config.json` via `config.get()`. No magic
  numbers in route files

## Stack

- Raw Node `http` (no Express, Koa, Fastify)
- `git` binary spawned for all repo operations
- Bare repos at `data/repos/<owner>/<name>.git`
- JSON state with atomic writes (`users.json`, `repos.json`)
- scrypt password hashing, HMAC-signed session cookies
- `git http-backend` CGI bridge for smart HTTP push/pull

## Layout

```
server.js              boot, route registration, listen
setup.js               creates admin, generates secrets
config.json            runtime tunables (generated by setup)
config.example.json
lib/
  config.js            layered config + setMany validate
  store.js             atomic JSON store
  respond.js           json/html/text + security headers + readJson
  router.js            :param pattern matcher
  log.js               leveled logger
  validate.js          name and path safety
  auth.js              scrypt + HMAC sessions
  limit.js             rate limit factory
  data.js              users.json + repos.json singletons
  git.js               spawn wrappers for every git op
  http-backend.js      smart HTTP CGI bridge
  render.js            templates, escape, sidebar, tree, blob, diff
  render-md.js         markdown safe subset
  render-diff.js       unified diff to HTML
routes/
  static.js            cached public assets
  auth.js              signup, login, logout, me, password
  repo-write.js        create, settings, rename, delete
  smart-http.js        info/refs, upload-pack, receive-pack
  pages.js             home, signup, new repo
  admin.js             admin settings page (full config control)
  repo.js              repo home, tree, blob, history, commit
  user.js              user profile
views/                 HTML templates
public/                style.css, pages.css, app.js, logo.png
scripts/
  smoke.js             end-to-end smoke test
data/
  users.json
  repos.json
  repos/<owner>/<name>.git/
```

## Setup

```
git clone https://git.dek.cx/dek/octuna.git otgit
cd otgit
node setup.js
npm start
```

`setup.js` prompts for admin username, password, public URL, and port,
then writes `config.json` and creates the admin user.

## Reverse proxy (nginx)

```
server {
  listen 80;
  server_name git.example.com;
  client_max_body_size 500M;
  location / {
    proxy_pass http://127.0.0.1:3031;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_request_buffering off;
    proxy_buffering off;
    proxy_read_timeout 300s;
  }
}
```

Then `certbot --nginx -d git.example.com`.

## Pushing code

```
git remote add origin https://git.example.com/<user>/<repo>.git
git push -u origin main
```

Use the account password as the git basic auth password. Public repos
clone without auth.

## Admin

The admin user (set by `setup.js`) sees an "Admin settings" link in
the sidebar. The page lets you edit any non-secret value in
`config.json` from the browser, with restart-required fields flagged.

## v1 scope

In: signup, login, password change, repo CRUD, file tree, blob viewer
with line numbers, commit history, single-commit diff with hunks,
README render, push/pull, admin settings, per-repo settings.

Out (post-v1): issues, pull requests, stars, forks, webhooks, CI,
releases, wikis, organizations, SSH transport, federation.

## License

MIT.
