gitreef
A minimal Git over SSH server implemented in Fish shell.
gitreef is designed for people who do not need a full Git hosting platform — no GUI, no databases, no management overhead. It provides only the essentials: SSH access, user and repository management, and basic access control.
As a result, it is small, secure, and fast, using under 10 MB of RAM, so it runs comfortably on modest hardware such as a Raspberry Pi.
Features
- Dockerized and easy to deploy
- Simple configuration via command line or Docker Compose
- Minimal dependencies: Git, SSH, Fish, Tini, Sudo
- Built-in user and repository management
- Basic ACL system with per-user read/write permissions
- Logging
Security
Protecting repositories from unauthorized access is a top priority. The server applies several hardening and sandboxing measures:
- Minimal Alpine base image with only essential tools installed
- Public-key authentication only (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 - A per-user ACL file checks permissions for each operation
- Logins for
rootand thegituser are disabled
Examples
Command Line
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
Notes
Any SSH key type supported by Git and your base system can be used. ACL files and repository definitions are recreated automatically on container restart.
License
GPLv3 — © 2026 Matthias Jaros
