Pretty much the moment I started to work with Git a few years ago, I’ve wanted to host my own server. I didn’t really bother looking into how that could work for a very long time. I assumed it would be rather complex considering Git itself is an extremely complex (set of) tool(s) to work with. I was hilariously wrong. It’s so simple to me that I’m under the impression that the lack of posts regarding the topic on blogs like this, is because it’s so simple. Still, I’m going to spend the rest of this post explaining how to set up a server and why even calling a basic configuration a server, is a bit of an exaggeration.
Setting up the server #
The first step is to set up a Unix box of any kind. Linux, any of the BSDs and probably even Darwin will work (hell, even Haiku might suffice). The rest of this post assumes a Debian system (or rather, that you have the core GNUtils available). Basics requirements are quite few:
- It needs to be accessible using SSH.
- It needs Git installed.
Adding an account #
Common practice dictates that you have a dedicated account for managing your Git repositories.
Common practice again dictates that this account be called
Its home directory doesn’t really matter, but I like tossing it into
Login shell also doesn’t matter yet, I tend to change it to
bash for when I need to do things as the
You can create an account with the following:
sudo useradd git -md /srv/git -s /bin/bash
-dspecifies where the home directory should be
-mcreates the home directory
-sspecifies what binary to use as login shell
Setting up SSH #
Client side #
On the machine from where you want to push your git repositories, generate a new SSH key to access your Git server:
ssh-keygen -t ed25519 -f ~/.ssh/<git-key>
I also recommend creating an entry in
~/.ssh/config for your Git server:
Host <host>-git Hostname <hostname> User git Identityfile ~/.ssh/<git-key>
Server side #
Next step is to make the
git account accessible over SSH.
ssh-copy-id won’t work because the
git user doesn’t have a password.
So instead, log in as the
git user and create a
.ssh directory with an
authorized_keys file with the public half of the
sudo su - git umask 077 # strict read write permissions mkdir ~/.ssh cat <git-key>.pub >> ~/.ssh/authorized_keys
Adding a repository #
You should now be able to log into your host as the
git user with using
Setting up the route from client to server is half the work.
Make this actually serve Git repositories.
All this requires is a bare Git repository somewhere within
To do this, log in as the
git user and run:
git init --bare <repo-name>.git
You now have a Git “server” with a repo named
To add something to this repo, on your client machine create a new repository and add
<host>-git:/srv/git/<repo-name>.git as remote and push your project to it.
Common practice dictates that this remote be called
mkdir my-fancy-project cd my-fancy-project git init git remote add origin <host>-git:/srv/git/<repo-name>.git echo "# Self-hosted repo!" > README.md git add -A git commit -m "Initial commit" git push -u origin main # assuming you use main as your default branch name
To clone this repository on another machine, add the
<git-key> SSH keypair and related configuration section in
~/.ssh/config to said machine and run:
git clone <host>-git:/srv/git/<repo-name>.git
Creating bare repositories by hand gets annoying quite quickly. I have an SSH forced command for another key that runs a script with the following:
#!/bin/sh BASELOC="/srv/git" echo "Enter new repo name:" read REPONAME [ -z $REPONAME ] && echo "No repo initialised" && exit 1 git init --bare $BASELOC/$REPONAME.git
authorized_keys entry for
command="/srv/git/.bin/new-repo" ssh-ed25519 <new-repo-git-key>.pub
Another thing you could do is change the login shell binary to a script that does something similar. I haven’t bothered to do so for reasons that presently escape me.