Have you considered hosting your own Git server? It's easier than you might think. In this article, I go step by step through setting up a simple self-hosted Git server which only supports private repositories for a single person.
Where do you currently host your Git repos? GitHub? BitBucket? GitLab?
Why not do it yourself?
Ok, there are reasons not to do it yourself. All of those services are fully featured products outside of Git, with user management, continuous integration, issue tracking, and basically free for most personal use. But it's also not as hard as you might think to just host Git yourself.
But why would you want to do this?
I want people to know how to do this because I'm a bit uncomfortable with the increasingly centralised nature of the internet, where it's controlled by a few massive corporations. I started hosting my own Git server as a learning exercise when Microsoft bought GitHub a few years ago. I don't think we all need to be hosting our own Git servers, but I think we should be able to if we need to. We should all be able to own our own data without being vulnerable to big companies changing the rules.
Packing away my tinfoil hat, it can also be useful to know just enough to set up something temporary for a week or two when the finance department forgets to pay for the Git hosting. Yes, this has happened to me.
I also wanted something specific: the ability to create as many private repos as I wanted, and to have them hosted close to home. I can rent a server that's physically located in the same city as me and run whatever I want on it, but the major Git hosting providers don't have servers in South Africa. I use Git a lot, and just having the Git server in South Africa with me decreases the latency on all Git fetches and pushes by a few hundred milliseconds. Not enough to have a real impact, but enough to be noticeable.
What will I cover in this article?
This article will cover setting up a simple Git server, meant for
only private repos,
for a single user (which may actually be multiple people).
There are a lot of other nice to haves and operational tricks that you might decide you want to add after this, but today I want to focus on the bare minimum.
This bare minimum is also enough for a lot of use cases. You can backup your local repos that you aren't sharing. You can sync your repos between multiple computers. You can even share your repos with someone else that you trust by sharing the user login. It's not web scale, but it is small web scale.
How do you host a Git server?
There's three steps to this:
Get a Linux server.
Add a user account with SSH access.
Let's get into it!
Get a Linux server
The first thing you're going to need is a Linux server. In terms of where to get that server, you have many options. There are a few big cloud computing companies that don't need my advertising. I wanted to have my server close to home, so my server is hosted by CloudAfrica. This server is for Git repos, which can get big depending on how much you put in them, so make sure you know how much you'll be charged for storage, and how much you'll be charged for moving data in and out. Luckily, if you're the only user, you can usually go with the least powerful cheapest server available (you can always move to a pricier one if you need it).
As an aside, you can completely do this with an old laptop. You'd just need to make sure you can connect to it from any computer you want to do Git stuff on. I went with a cloud server because it's easier to get it available on the internet that way.
I'm not going to give specific steps for how to create a Linux server because it will vary from platform to platform and also on your particular flavour of Linux, but here's some stuff to look out for:
Your server needs to have a public IP address so you can connect to it from anywhere.
If your hosting platform has a firewall, you'll need to open port 22 for incoming traffic. This is because Git will be connecting using SSH, which connects on port 22.
You'll probably get a choice of hard drive space. Take a look at what you want to push and how big it is to figure this out, and make sure you add a small buffer for things to grow.
You'll need a way to connect to your new server. For many cloud platforms, you'll do this by giving them an SSH public key which will let you SSH into the server after it's up. This is good, because you need to setup SSH later anyway for Git.
As an optional extra step, if you happen to have a domain, you can add a DNS record to point at your server. Which type of record will depend what your hosting platform gives you. If you can refer to your server by IPv4 address, then you need to add an A record. If you can refer to your server by IPv6 address, then you need an AAAA record. If your hosting platform shares IP addresses and only lets you refer to your server by URL, then you'll need a CNAME record. I added a subdomain to my website's domain, so code.worthe-it.co.za points at my Git server. If you don't have a domain, you can still refer to your server by IP address or a URL provided by your hosting platform, it's just nicer to type a domain name.
I provided my SSH key as part of the CloudAfrica sign up process, so at
the end of this step I could login to my new server with
Create a user account for yourself with SSH access
Chances are when you set up your server it gave you a root account. In theory you could just use the root user as your Git user, but it's generally better security practice to do most things with a normal user account that doesn't have the power to break everything.
User management and SSH key management for those users is pretty common, so if your cloud platform has a way to add a user you could just use their tools and skip this whole section. However, if you're not so lucky, you can open a terminal with that root user and do it yourself.
# Feel free to call your user account justin. # Or swap it out for your own name if you prefer. useradd justin
Next, you need to set up a way for Git to login to access your repos. To do this, you need your server to be running an SSH daemon. SSH (short for secure shell) is a way for you to login to a server remotely. There's a good chance that your server already has this set up, but if it's not you can just install it yourself.
# This might be called something different on your distro, and if # you're using a cloud service it's probably already installed. apt install openssh-server systemctl enable ssh.service systemctl start ssh.service
You might want to take a look at the SSH config and see if the settings make sense for you. The config file is generally filled, with all of the default options commented out, so it's easy to read through and see what the options are. Many people disable password-based authentication, and disable logging in as root, but if you're doing this be careful not to lock yourself out.
nano /etc/ssh/sshd_config # if you made any changes, you'll need to restart the service for the # changes to take effect. systemctl restart ssh.service
When you're happy with your SSH daemon config, it's time to upload
your SSH public key. This is the same SSH public key that you would
have uploaded to other managed Git servers. The only difference is
that you need to put it in a specific file rather than uploading it
through a web interface. It needs to go in
~/.ssh/authorized_keys. We'll put your ssh public keys on the server
scp (secure file copy, essentially
ssh), and then
login and stick it on the end of the
# This part is run on your computer (not the server). It's based on # Linux, so if you're on Mac or Windows you may need to do the # equivalent for your platform. # If you don't already have an SSH key, you need to make one. If you # already have one that you use with GitHub / GitLab / BitBucket / # Whatever, then you can just use the same one. ssh-keygen # We're doing this as root because we can't ssh in as "justin" yet. If # you're adding a second key later and still have the first, you can # do this without the root account. scp ~/.ssh/id_rsa.pub root@your-cool-server-ip:new_ssh_key.pub
Now that you've uploaded your SSH key, you need to put it in the right place. Login as root and then do the following:
# These steps should be run on the server. # Remember to swap out "justin" for your username. This will show you # if the .ssh folder and the authorized_keys files already exist. ls -l /home/justin/.ssh/ # If .ssh doesn't exist, you'll need to create it. Skip this if the # .ssh directory already exists. mkdir /home/justin/.ssh chown justin:justin /home/justin/.ssh chmod 700 /home/justin/.ssh # If authorized_keys doesn't exist, you'll need to create that # too. Skip this if authorized_keys already exists. touch /home/justin/.ssh/authorized_keys chown justin:justin /home/justin/.ssh/authorized_keys chmod 600 /home/justin/.ssh/authorized_keys # Now that everything exists, stick your new key on the end cat new_ssh_key.pub >> /home/justin/.ssh/authorized_keys
If that all worked correctly, you should now be able to ssh in as your new git user.
# If you can run this on your computer (not the server) and it gives # you a shell on the server, you have SSH access! ssh justin@your-cool-server-ip
This simple setup gives you only one user account. If you want to
share your git repos with someone else, or share with yourself on
another computer, you can repeat adding SSH keys to the end of
authorized_keys as many times as you like. If you do add other
people this way, just keep in mind that there's only one user account
from the server's point of view, so all the repos are shared.
You don't need any fancy Git package here. You just need the normal Git package in the distro that you're working on installed.
On Ubuntu, this meant running.
apt install git
You know you're done if you can run git.
git version 2.36.0
Believe it or not, you now have a functioning Git server. All you need is a server with Git installed, and a user that can log into that a server over SSH.
How do you use your new Git server?
Creating a new repository
To create a new repo, you ssh in and run
git init. Since nobody is
actually working on the repository directly on the server, you'll
generally want to create a "bare" repo. Bare repos are basically just
.git directory, they don't have a checked out working copy of
# Use ssh to connect to your server ssh justin@your-cool-server-ip # Then run git init on the server (in the ssh session) git init --bare my-awesome-project.git
You can now clone your repo and do anything that you might have done with it if it were hosted elsewhere.
# The justin@your-cool-server-ip part here is the same username and # hostname you'd call ssh with to login. # # Anything after the colon (:) is relative to your home directory on # the server. git clone justin@your-cool-server-ip:my-awesome-project.git
All of your normal Git stuff using your new Git server should just work!
Where can I learn more?
The best source that I found explaining how to do this was in an online book called Pro Git. It has a chapter on hosting your own Git server, and goes into much more detail on the setup and various options than I have in this article.
What's missing, and what next steps did I take?
For my own Git server, I didn't stop here.
I script server setup and changes with Ansible.
I allow browsing of open source repos using CGit.
I regularly backup all of my Git repos using Duplicity.
I restrict my Git user's permissions by using Git Shell.
I have other users on my server, and share repos using Linux user permissions.
I also have plans for the future.
I'm going to add support for other version control programs. For example, I want to try putting certain repos into Pijul instead of Git.
I've been playing with an idea for a different way of doing continuous integration on personal projects. Since I control the Git server, I can add a web dashboard for it.
I'm probably missing a lot when it comes to keeping my server running reliably, making it easy to make changes, scaling, and all sorts of other things that I still don't know about. Operations and site reliability engineering are their own massive discipline. I'm a developer primarily, doing ops badly, and that's OK. One of the great things of being small web scale is that it only needs to support my own needs.
I chose to start hosting my own Git server because I wanted to learn from it, I wanted to control my own data, and I enjoy trying out this sort of thing. It's obviously much more work and much more manual than signing up to some managed service. But it's been working well for me, and I'm having fun. I hope that if you try it out, you also learn a lot and have fun doing so.