Shrugs: A Self Hosted Git SSH Server
shrugs is an Apache licensed self hosted git server available as a docker container written in Erlang and Rust.
Sometimes you just want to host some local changes before publishing to the cloud, using a simple git server than can easily run on something as small as a Raspberry PI.
Quick Start
You can run shrugs
in a docker container with:
docker run \
--name shrugs \
-d \
-p 22022:22 \
ghcr.io/shortishly/shrugs
The container supports both amd64
and arm64
architectures.
Authentication
Copy your authorized_keys
into the container for authentication:
docker cp ~/.ssh/authorized_keys shrugs:/users
Or copy the public key of individual users:
docker cp bob.pub shrugs:/users
docker cp alice.pub shrugs:/users
New keys (“*.pub” or “authorized_keys”) in the users directory will be picked up every 5 seconds.
Push
Push a repository into shrugs with:
mkdir demo
cd demo
git init .
echo "world" > hello.txt
git add hello.txt
git commit --message='demo'
git branch -M main
git remote add origin ssh://localhost:22022/demo
git push --set-upstream origin main
A new repository will be automatically created (with git init
--bare
) to receive your changes, when pushing a new repository into
shrugs.
Clone
Clone the demo
repository as abc
:
git clone ssh://localhost:22022/demo abc
Add some more content and push to the existing repository:
cd abc
echo "God’s Own Country" > yorkshire.txt
git add yorkshire.txt
git commit --message='home'
git push origin main
ls
To list (ls) the repositories stored in shrugs:
$ ssh -p 22022 localhost ls
demo
~/.ssh/config
With the addition of a host entry for shrugs in your .ssh/config
:
host shrugs
hostname localhost
checkhostip no
stricthostkeychecking no
loglevel QUIET
port 22022
Results in a bit less typing:
$ ssh shrugs ls
demo
$ git clone ssh://shrugs/demo
Cloning into 'demo'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (6/6), 466 bytes | 155.00 KiB/s, done.
$ cd demo
$ git remote -v
origin ssh://shrugs/demo (fetch)
origin ssh://shrugs/demo (push)
compose.yaml
An example compose.yaml
with volume mounts for /repos
(git
repository storage), /etc/ssh
(shrugs ssh host key), and /users
(user public keys).
---
services:
shrugs:
image:
${SHRUGS_IMAGE:-ghcr.io/shortishly/shrugs:${SHRUGS_VERSION:-latest}}
ports:
- 22022:22
pull_policy:
${PULL_POLICY:-always}
volumes:
- repos:/repos
- host_keys:/etc/ssh
- user_keys:/users
volumes:
repos:
driver: local
host_keys:
driver: local
user_keys:
driver: local
With the above you can copy keys with docker compose cp rather than docker cp:
docker compose cp bob.pub shrugs:/users
docker compose cp alice.pub shrugs:/users
Environment
The following environment variables can be used for configuration:
Variable | Default | Description |
---|---|---|
SHRUGS_SSHD_PORT | 22 | Incoming SSH connections on this port |
SHRUGS_AUTHENTICATION_ENABLED | true | “false” will disable user authentication |
SHRUGS_SYSTEM_DIR | /etc/ssh | This directory to find the host key |
SHRUGS_USER_DIR | /users | This directory to find authorized user keys |
SHRUGS_REPO_DIR | /repos | This directory to store git repositories |
SHRUGS_BIN_DIR | /bin | This directory to find the git executable |
SHRUGS_WATCH_TIMEOUT | 5000 | Check the repo dir every 5000ms for new user keys |
SHRUGS_INITIAL_BRANCH | main | Initial branch name used with git –init –bare |
Debug
The following environment variables can be used to enable debug logging:
Variable | Default | Description |
---|---|---|
SHRUGS_KEY_STORE_TRACE | false | Enables logging options from the key store |
SHRUGS_SSH_DAEMON_TRACE | false | Enables logging of the SSH daemon |
SHRUGS_USERS_TRACE | false | Enables logging of the users subsystem |