legit
A git web frontend written in Go.
Pronounced however you like; I prefer channeling my inner beret-wearing
Frenchman, and saying "Oui, il est le git!"


---
## What is legit?
`legit` is a self-hosted git repository browser for the web. Point it at a
directory full of repos and it'll give you a clean, modern web interface for
browsing files, viewing commits, exploring branches and tags, and cloning over
HTTPS.
It's not CGI. It's not Gitea. It's just a single binary that serves your repos.
## Quick start
```bash
# Build
go build -o legit
# Run
./legit --config ./config.yaml
```
You'll need a `config.yaml` (see [Configuration](#configuration)) and at least
one bare git repo in your `scanPath`.
## Features
| | |
|---|--------------------|
| 🖥️ | Browse repos, files, trees, and commits |
| 🌲 | File tree view with mode and size |
| 📜 | Commit log with full diff output |
| 🏷️ | Tag and branch listing |
| 📦 | Archive downloads (tar.gz) |
| 🎨 | Syntax highlighting (chroma) |
| 🪨 | Markdown readme rendering |
| 🔗 | Cloning over HTTPS (smart HTTP protocol) |
| 📄 | Templated HTML (fully customisable) |
| 🌙 | Dark mode (CSS media query) |
## How do I configure legit?
Configuration is via `config.yaml`. By default it looks in the current
directory; use `--config ` to point elsewhere.
```yaml
repo:
scanPath: /var/www/git
readme:
- README.md
- README
mainBranch:
- master
- main
ignore:
- foo
unlisted:
- private-repo
dirs:
templates: ./templates
static: ./static
meta:
title: git good
description: come get your free software
syntaxHighlight: monokailight
server:
name: git.example.com
host: 127.0.0.1
port: 5555
```
| Field | Description |
|-------|-------------|
| `repo.scanPath` | Directory containing repos (flat — subdirectories are not traversed) |
| `repo.readme` | Readme filenames to look for (first match wins) |
| `repo.mainBranch` | Branch names to try as default branch |
| `repo.ignore` | Repos to exclude entirely (returns 404) |
| `repo.unlisted` | Repos to hide from the index (still accessible by URL) |
| `dirs.templates` | Path to custom Go html/template files |
| `dirs.static` | Path to custom static assets (CSS, images) |
| `meta.syntaxHighlight` | [Chroma style](https://swapoff.org/chroma/playground/) for syntax highlighting; empty = no highlighting |
| `server.name` | Used for `go-import` meta tags and clone URLs |
## What about cloning?
Cloning works over HTTPS via git's smart HTTP protocol.
```
git clone https://git.example.com/my-repo
```
**Things to know:**
- Cloning only works with **bare repos** (a limitation of git itself — non-bare
repos still display fine in the web UI).
- Pushing over HTTPS is deliberately **disabled**. Use SSH.
- Run legit behind a TLS-terminating proxy (nginx, relayd, etc.).
## How does one host it?
```bash
# Docker
docker run -p 5555:5555 \
-v /var/www/git:/var/www/git \
ghcr.io/icyphox/legit:latest
# systemd (see contrib/legit.service)
systemctl enable --now legit
```
Pre-built Docker images are available at
`ghcr.io/icyphox/legit:{master,latest,vX.Y.Z}`.
## Building
```bash
go build -o legit
```
No external dependencies beyond the Go toolchain. A Nix flake is also available
for reproducible builds (`nix build`).
## How does it work?
```
HTTP request
↓
┌────────────┐
│ main.go │ Parse config, unveil(2) on OpenBSD
└────────────┘
↓
┌────────────┐
│ routes │ Route requests: web UI or git smart protocol
│ handler.go │
└────────────┘
↓
┌────────────┐
│ git/ │ Read repos via go-git, exec git-upload-pack
└────────────┘
↓
┌────────────┐
│ templates │ Render HTML via Go html/template
└────────────┘
```
The `/{name}` endpoint is a **multiplexer**: it detects git HTTP protocol
requests (`info/refs?service=git-upload-pack`, `git-upload-pack` POST) and
routes them to the git backend, or renders the web UI otherwise.
## Licence
Original code (c) Anirudh Oppiliappan — MIT.
Modifications (c) Maxwell Jensen — [European Union Public Licence 1.2](https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12).
See `license` and `NOTICE` for details.