Build automatically with gpb-docker
Update example compose file
Add the ability to send secrets to builders
jasoncarloscox.com/creations/git-personal
A Docker image for a simple, single-user Git server. Also available as a pre-built image on Docker Hub.
git-shell
First, you'll need to create an authorized_keys
file containing your current public SSH key and generate an SSH key pair to be used by the server. Put them all inside a single directory:
$ mkdir git-personal-ssh
$ cat ~/.ssh/id_rsa.pub > git-personal-ssh/authorized_keys
$ ssh-keygen -f git-personal-ssh/id_rsa -C git-personal # leave passphrase empty
Then you can start the server:
$ docker run \
--publish 2222:22 \
--volume git-repos:/home/git \
--volume ssh-host-keys:/etc/ssh/host_keys \
--volume ./git-personal-ssh:/home/git/.ssh \
jasonccox/git-personal
See the example Compose file for documentation about the volume mounts.
Once the server is running, you can access it over SSH like so:
$ ssh -p 2222 git@some.host # or whatever host it's running on
Doing so will drop you into git-shell
on the server, where a few commands are available:
help Print available commands
repo new NAME Create a repo NAME
repo new -f|--from REMOTE NAME Create a repo NAME that is a copy of
REMOTE
repo list|ls List all repos
repo remove|rm NAME Remove the repo NAME
mirror new NAME REMOTE Set repo NAME to mirror to REMOTE
mirror remove|rm NAME REMOTE Set repo NAME to stop mirroring to
REMOTE
mirror list|ls NAME List remotes to which repo NAME is
mirroring
builder new NAME BRANCH BUILDER Set repo NAME to trigger builds on
BUILDER when new commits are pushed
to BRANCH (use 'all' for any ref).
builder remove|rm NAME BRANCH BUILDER Set repo NAME to stop triggering
builds on BUILDER when new commits
are pushed to REF.
builder list|ls NAME [BRANCH] List builders which are triggered
when new commits are pushed to BRANCH
(omit for all branches) in repo NAME.
secret new KEY VALUE Create a secret named KEY with value
VALUE.
secret list|ls List all secret names.
secret remove|rm KEY Remove the secret named KEY.
These commands can also be run directly over ssh, e.g. ssh -p 2222 git@some.host repo new my-repo
. When accessing the server non-interactively like this, a few additional server-side Git commands are also available; see man git-shell
for more information.
Once you've created a repo, you can interact with it via Git over SSH. By default, repos are created in /home/git/
on the server.
For example, if you had a local repo called my-repo
, you might do the following to create a repository, push some code to it, and mirror it to SourceHut:
# create the repo on the server
$ ssh -p 2222 git@some.host repo new my-repo
# add the server repo as a remote and push to it
$ cd my-repo
$ git remote add origin ssh://git@some.host:2222/~git/my-repo.git
$ git push -u origin master
# mirror to SourceHut (the repo must already exist on SourceHut, and your
# server's SSH key must have access)
$ ssh -p 2222 git@some.host mirror new my-repo git@git.sr.ht:~me/my-repo.git
You can change the server directory in which the Git repos are stored by setting the GIT_REPO_DIR
environment variable in the Docker container.
You can change the user ID and group ID of the git user via the GIT_UID
and GIT_GID
environment variables in the Docker container.
Additional customization is possible by building your own Docker image based on git-personal.
Check out the example Compose file.
If your git-personal server is available over a port other than SSH's standard 22, you can eliminate the need to specify the port by adding the following to the end of your SSH config:
Host some.host # the hostname you use to access git-personal
Port 2222 # the port exposed for git-personal
Notably, this allows you to access the server without the -p
flag (e.g. ssh git@some.host
instead of ssh -p 2222 git@some.host
) and provide scp-style URLs to Git (e.g. git clone git@some.host:my-repo.git
instead of git clone ssh://git@some.host:2222/~git/my-repo.git
).
You can even take this one step further and eliminate the need to specify the git
user by adding User git
to your SSH config as well.
You can organize your repos in subdirectories by specifying a path as the repo name:
$ ssh -p 2222 git@some.host
git> repo new cool-project
git> repo new code/awesome-sauce
git> repo new code/web/my-site
git> repo ls
cool-project
code/awesome-sauce
code/web/my-site
git> exit
$ git clone ssh://git@some.host:2222/~git/cool-project.git
$ git clone ssh://git@some.host:2222/~git/code/awesome-sauce.git
$ git clone ssh://git@some.host:2222/~git/code/web/my-site.git
With the help of git-personal-builder, you can configure a repository to trigger builds each time you push to it.
First, create and setup a builder container. Then, configure your repository to trigger a build on each push to BRANCH
:
git> builder new REPO BRANCH URL
REPO
: The name of the repository which should trigger builds.BRANCH
: The name of the branch which should trigger builds.URL
: The base URL of the builder container, e.g. https://builder.example.com
.If you use a Compose file to run git-personal, you can run the build container next to it and then address it with the build container's service name, e.g.
http://build-service
.
You can store secrets in git-personal so that they are automatically sent to builder containers for each build. See the secret ...
commands above.
Each secret has a key (name) and a value. The key may have a path-like structure, and all but the last element of this path will be used to determine which build containers it will be sent to. If the secret's path, minus its last element, is a prefix of the path of the repo for which the build was triggered, then the secret will be sent.
For example, consider three secrets -- s1
, dotfiles/s2
, and school/s3
-- and three repos -- dotfiles
, personal/cool-game
, and school/my-project
. When a build is triggered for the dotfiles
repo, it will be sent the secrets s1
and dotfiles/s2
. When a build is triggered for the personal/cool-game
repo, it will be sent only the s1
secret. When a build is triggered for the school/my-project
repo, it will be sent the s1
and school/s3
secrets.
Secrets are stored in /etc/secrets
(or the runtime value of SECRET_DIR
in the environment). You likely want to mount a volume at this directory so your secrets persist across container restarts.
Contributions are welcome! You can send questions, bug reports, patches, etc. by email to ~jcc/public-inbox@lists.sr.ht. (Don't know how to contribute via email? Check out the interactive tutorial at git-send-email.io, or email me for help.)