Welcome to gitreef — a GIT over SSH server implemented using fish.
The goal of this project is to provide a minimal Git server with no unnecessary features or management overhead. It’s designed for everyone who doesn’t need or want a fancy GUI or advanced functionality beyond the essentials. As a result, it’s small, secure, fast, and uses under 10 MB of memory, so it runs easily even on less powerful hardware like a Raspberry Pi.
- 🐳 Dockerized
- ⚙️ Simple configuration via command line or Docker Compose
- 🚀 Fast & secure, with minimal dependencies: Git, SSH, Fish, Tini, Sudo
- 👥 Built-in user and repository management
- 🔐 Basic ACL system with per-user read/write permissions
- 📜 Logging
Keeping your repositories safe from unauthorized access is a top priority. This server applies multiple hardening and sandboxing measures, such as:
- Minimal Alpine base image with only essential tools installed
- Only public-key authentication (no passwords)
- No TTY and no interactive shell logins
- All Git commands are sanitized and validated
- Repositories are stored under
/srv/reposand cannot access paths outside that directory - Per-user ACL file checks permissions for each operation
- Root and “git” user logins are disabled
docker run --rm -p "2222:22" jarlucmat/gitreef -u "user1:ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbm
lzdHAyNTYAAABBBPsl91WPAT8aWwZ6y5WAfXU9PoHzxJ3YG9uFgSmlGQr2HwV+gL/XaTBJ4Brj+pa+R7tfYEBMi+7Navx/ZsEmr9E= mj@xps15" -r "/repo1.git;user1:w"Docker Compose:
services:
gitreef:
image: jarlucmat/gitreef
ports:
- "2222:22"
environment:
# Note: Variable names cannot contain dashes, but values can!
# UID/GID of the user that owns all repositories
- GIT_UID=1000
- GIT_GID=1000
# Users in the form USER_<id>=<username>:<ssh-public-key>
- USER_user1=user1:ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPsl91WPAT8aWwZ6y5WAfXU9PoHzxJ3YG9uFgSmlGQr2HwV+gL/XaTBJ4Brj+pa+R7tfYEBMi+7Navx/ZsEmr9E= mj@xps15
- USER_user2=user2:ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPsl91WPAT8aWwZ6y5WAfXU9PoHzxJ3YG9uFgSmlGQr2HwV+gL/XaTBJ4Brj+pa+R7tfYEBMi+7Navx/ZsEmr9E= mj@xps15
# Repositories in the form REPO_<id>=<path>;<user>:<perm>[;<user2>:<perm>;...]
# Permissions:
# r = read
# w = write
# A user without a permission flag has read access by default.
- REPO_repo1=/repo1.git;user1
- REPO_repo2=/repo2.git;user2:w
- REPO_repo3=/repo3.git;user1:r;user2:w
volumes:
# Basic volumes that should be mapped
- ./ssh:/var/ssh
- ./repos:/srv/repos
- ./log:/var/logYou can use any SSH key type supported by Git and your base system. Logs are written to /var/log/git-run by default. ACL files and repository definitions are recreated automatically on container restart.
GPLv3 © 2025 Matthias Jaros