Create a personal Git server!

Published: 2022-09-10 - Updated: 2022-09-10


The way we'll set this up is that only you will be able to push and everyone else will be able to just pull and clone your repository. Note: I'll be using Debian for this guide, and instructions may vary depending on what distribution you're on. First, we'll set up a git user, which will be used to manage our repositories.

apt-get install git
useradd -m git
su git
mkdir .ssh repos && chmod 700 .ssh
touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys

I expect you to already have a pair of ssh keys configured, you should copy them to /home/git/.ssh/authorized_keys or generate a pair of new ones.

Now to be able to have users be able to clone your repositories, you'll have to start a Git daemon. Create the file /etc/systemd/system/gitd.service with the following contents:

Description=Git Daemon

ExecStart=/usr/bin/git daemon --reuseaddr --export-all --base-path=/home/git/repos/ /home/git/repos/




Now just enable and start the service. Also, if you're running a firewall, you'll need to allow 9418/tcp.

systemctl enable --now gitd

Managing repositories

Well, a Git server without any repositories is quite useless. Creating a repository is done by initialize them in the repos/ folder.

cd repos
mkdir project
cd project
git init --bare

You may also want to modify the owner and description file inside the folder, these will be used for the front-end we'll be installing next. To push to your newly created repository, you do the following.

mkdir project
git init
git remote add origin git@IP_OR_HOSTNAME:/home/git/repos/project
git add .
git commit -m 'Initial commit'
git push origin master

For those who wish to clone your repository, they can do git clone git://IP_OR_HOSTNAME/project

A simple front-end

You may want to be able to display all your Git repositories on your website, for this we can use stagit. To get an idea, how it will look, you can take a look at /git/. To install stagit, we will need to first compile it, this can be done in the following manner

apt-get install build-essential libgit2-dev
git clone git://
cd stagit
sed -i s/\#STAGIT/STAGIT/g Makefile
make install
cd /home/git/repos/

The usage of stagit is a bit weird, therefore we will create a script to generate it for us. I recommend placing the script in /home/git/repos/ Note: the script expects the following files style.css, favicon.png, logo.png inside that directory. Also, don't forget to make it executable with chmod +x!


cd /home/git/repos
bash -c '/usr/local/bin/stagit-index $(find -maxdepth 1 -type d | grep /) > index.html'
bash -c 'for dir in $(find -maxdepth 1 -type d | grep /); do
        cd "${dir}"
        find style.css >/dev/null 2>&1; [[ $(echo $?) == 1 ]] && ln -s ../style.css
        find favicon.png >/dev/null 2>&1; [[ $(echo $?) == 1 ]] && ln -s ../favicon.png
        find logo.png >/dev/null 2>&1; [[ $(echo $?) == 1 ]] && ln -s ../logo.png
        find url >/dev/null 2>&1; [[ $(echo $?) == 1 ]] && formatdir=$(echo ${dir} | cut -d / -f 2) && echo "git://IP_OR_HOSTNAME/${formatdir}" > url
        /usr/local/bin/stagit ./
        cd ..
cd $wd

We probably don't want to run this manually every time we make a change, therefore we will set up a cronjob to automatically update it every 5 minutes.

su git -c "crontab -e"

*/5 * * * * bash /home/git/repos/

And it's done, now you'll just have to point your HTTP server to /home/git/repos/! Oh, and now that everything is set up, you may also want to disable shell access for the git user and only allow git operations.

chsh git -s $(which git-shell)
Questions or comments? contact me!