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!"

![Codeberg Release](https://img.shields.io/gitea/v/release/maxwelljensen/legit?gitea_url=https%3A%2F%2Fcodeberg.org&style=for-the-badge) ![Codeberg License](assets/eupl-12-badge.svg) --- ## 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.