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
# Build
go build -o legit
# Run
./legit --config ./config.yaml
You’ll need a config.yaml (see below) 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 <path> to point elsewhere.
repo:
scanPath: /var/www/git
readme:
- README.md
- README
mainBranch:
- master
ignore:
- foo
unlisted:
- private-repo
dirs:
templates: ./templates
static: ./static
meta:
favicon: favicon.svg
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 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?
# 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
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 © Anirudh Oppiliappan under MIT Licence.
Modifications © Maxwell Jensen under European Union Public Licence 1.2.
See LICENCE.txt for details.