Ferrenium
A read-only Git repository browser, like cgit, as a single Rust daemon. It serves every bare repository under one directory and keeps no state on disk.
Pages: repo index, summary + README, tree, file (highlighted), raw, log
(path filter, message search), commit + diff, .patch, blame, refs, file
finder, .tar.gz/.zip snapshots, Atom feed. git clone over HTTPS
(read-only).
Install
On a Linux host with systemd (x86_64 or aarch64, glibc 2.28+):
curl -fsSL https://github.com/krolyxon/ferrenium/releases/latest/download/install.sh | sudo FERRENIUM_DOMAIN=git.example.com sh
This:
- downloads the latest release binary, verifies its checksum and installs it to
/usr/local/bin/ferrenium - creates the
gituser if it doesn't exist (home/home/git, shellgit-shell) - writes
/etc/ferrenium/ferrenium.toml(never overwritten on later runs) - installs
/etc/systemd/system/ferrenium.serviceand runssystemctl enable --now ferrenium
Variables: FERRENIUM_DOMAIN (fills base_url and clone URLs in a new
config), FERRENIUM_USER (default git), FERRENIUM_VERSION (e.g.
v0.1.0, default latest).
Run the same command again to upgrade: it replaces the binary and unit
and restarts the service. To remove it: … | sudo sh -s -- --uninstall.
This keeps /etc/ferrenium and the repositories.
The service
It's a normal system service. The unit has User=git, so systemd starts it
as the repo owner. You don't need su git or systemctl --user.
sudo systemctl status ferrenium
sudo systemctl reload ferrenium # after editing the config
sudo journalctl -u ferrenium -f
sudo systemctl edit ferrenium # overrides; survive upgrades
The unit is sandboxed: the filesystem is read-only, there are no capabilities, a syscall filter applies, and only localhost may connect.
Reverse proxy
Ferrenium listens on 127.0.0.1:8080 (plain HTTP/1.1). Caddy:
git.example.com {
reverse_proxy 127.0.0.1:8080
}
If Caddy runs in Docker, use network_mode: host so it can reach
127.0.0.1.
Repositories
Put bare repositories anywhere under /home/git (up to 3 levels deep).
Ferrenium picks up new repos and pushes within about a second.
sudo -u git git init --bare /home/git/project.git
git push git@git.example.com:project.git main # after adding your key to /home/git/.ssh/authorized_keys
Configuration
Edit /etc/ferrenium/ferrenium.toml. Every key is optional and unknown
keys are errors. The file lists all keys with their defaults
(ferrenium example config prints the same). To validate the config and
list the repositories it finds:
ferrenium check --config /etc/ferrenium/ferrenium.toml
listen, base_path, compression, cache.size_mb and the limits.*_parallel/max_requests
settings need a restart; everything else applies on reload.
Per-repository metadata comes from the first source that sets it:
[[repo]]in the config (name,description,section,owner,hidden,readme,default_branch)- the repo's git config:
ferrenium.{description,owner,section,hidden,readme}, or the gitweb/cgit keys - the repo's
descriptionfile
sudo -u git git -C /home/git/secret.git config ferrenium.hidden true
Limits
Defaults are sized for a small VPS:
| Key | Default | |
|---|---|---|
limits.git_parallel |
CPUs, max 8 | concurrent git work |
limits.heavy_parallel |
2 | concurrent blame / archive / clone / log search |
limits.heavy_wait_secs |
10 | queue time for those before 503 |
limits.max_requests |
512 | in-flight requests before 503 |
limits.request_timeout_secs |
30 | until the response starts |
limits.diff_files / diff_lines |
300 / 10000 | larger diffs are truncated |
ui.max_blob_kb / max_highlight_kb |
1024 / 256 | larger files: raw link / no highlighting |
cache.size_mb |
64 | in-memory cache |
/robots.txt keeps crawlers off the expensive pages. Memory use at idle is
about 10 MB.
Building from source
Requires Rust 1.89+.
cargo build --release # target/release/ferrenium
ferrenium example config|systemd|caddy
Development
cargo test # needs the git CLI
cargo test --release
cargo clippy --all-targets -- -D warnings
cargo run -- serve --config dev.toml
tools/gen-languages/gen.py # regenerate the Linguist language table
To release: bump version in Cargo.toml, commit, then push a vX.Y.Z tag.
The release workflow tests, builds x86_64 and aarch64 binaries, and
publishes them with install.sh and SHA256SUMS.
License
GPL-3.0 (see LICENSE). Bundled fonts (Doto, Space Grotesk, Space Mono)
are licensed under the OFL; see assets/fonts/OFL.txt. Icons come from
Lucide (ISC license).