Install a self-hosted Git server with Gitea

In this tutorial we will install a Gitea Git server on our VPS. This article starts where the previous article about setting up a VPS ended.

There are a lot of Git servers available that you can self-host. I chose Gitea for this example because it's very easy to install. Gitea is written in Go and you only have to install one binary file. Gitea is a fork of Gogs, so the following tutorial is also applicable for a Gogs installation. See this page for the reasons why they forked Gogs.

Before we start with the installation we buy and set up a domain name. Technically this is not really necessary but a domain name is a bit easier to remember than an IP address.

Many companies sell domains on the Internet. One service I use is Hover and my .ch domains I bought from https://www.myhosttech.eu, a swiss based company.

It's difficult to give advice which company to choose. Check also the website of your VPS provider, it's possible that they sell domain names too. Compare prices they can differ from registrar to registrar. Usually the domain name is something you have to pay yearly. The cheapest domains cost about 10 USD per year, catchy domain names usually cost a lot more.

For this blog post I will use the domain ralscha.ch that I already own and set up a subdomain: git.ralscha.ch. The Git server will then be accessible with the URL https://git.ralscha.ch

I like to use different subdomains for my self-hosted services, it makes the http server set up more convenient. You don't have to worry about TLS certificate costs because we will create Let's Encrypt certificates, they are free and you can create as many as you want.

Make sure, when you follow this tutorial, to replace git.ralscha.ch with your domain name.

After you bought the domain name, log in to the registrars web management interface. There you should find a function that allows you to add DNS records. You have to add an A record that points from the domain name to the IPv4 address of your server

If your VPS provider also set up a static IPv6 address add an AAAA record with the same domain name but the IPv6 address of your server.

You can test the DNS configuration when you open a shell or command prompt on your computer and issue a ping

ping git.ralscha.ch

When the command is able to resolve the domain name, it sends a few ping requests to the server. If it is not able to translate the name to the IP address it prints out an error. It can take a few minutes until the changes in the DNS are visible to the public.

Next we create a link to our service file in /lib/systemd/system. This is the directory where systemd looks for service files. Reload the systemd daemon. You need to reload systemd each time a service file changes.

From time to time you should check if there is a new Gitea version available. To update Gitea run the following commands. I always keep a copy of the last version if something does not work with the update.

In this section we install a http server. The servers sits in front of the Gitea server and proxies all requests coming from the clients to Gitea. When you only have one service this might be a bit overkill, but as soon as you start installing a second service with a web interface you see the benefit of having a http server. The http server is also responsible for managing the TLS connection.

Two popular open source http servers are nginx and Apache. I prefer nginx and use it on all my servers, but if you have more experience with Apache install that server, it will work too.

Install nginx with apt

sudo apt update
sudo apt install nginx

Open ports 80 and 443 in the firewall. 80 for unencrypted http and 443 for encrypted http (TLS) traffic.

The configuration also increases the maximum allowed size of the client request body to 20 MB. By default nginx only allows a request body size of 1MB. If you need to commit files that are bigger than 20 MB you need to increase the value.

Open a browser and enter the URL http://git.ralscha.ch. Gitea should display the initial installation dialog.

Gitea requires a database and supports many different database servers. I prefer SQLite3 which is an embedded database and don't need additional setup. Change the path to the database: /home/git/gitea/data/gitea.db

Under Optional Settings -> Server and Other Services Settings I select these options. Depending on your use case select other options. Don't select Disable Self-Registration.

Click on the Install Gitea button at the bottom of the page. After a few seconds Gitea should present the login screen, if not enter the URL http://git.ralscha.ch/user/login manually. Setup the first user. Click on Sign up now, create an account and login with this account. The first user you create has administrator permissions.

With this configuration self-registration is enabled. Everybody in the world that knows the URL of your server can create an account. If you want to disable this open the configuration file sudo nano custom/conf/app.ini and search for the line

We can now create our first Git repository. Login and create a new repository. Gitea supports public and private repository. Public repositories are visible to everyone, even visitors that don't have an account. It's very similar to the public repositories on GitHub.

On your local computer clone the repository, create a file, add and commit it and then push it to the remote repository

We have a working Git server but the communication between our computer and the server is unencrypted. In this section we change that and install a TLS certificate in nginx.

First we install the Let's Encrypt client certbot. This program is responsible for creating and renewing certificates. Certificates from Let's Encrypt are free but they are only valid 90 days. certbot installs a job that runs periodically and checks for outdated certificates and automatically renews them.

When you have TLS certificates, you should always add a CAA record to your domain name. A Certification Authority Authorization (CAA) record is used to specify which certificate authority (CA) is allowed to issue certificates for a domain. CAs have to check this record, if not present any CA is allowed to issue a certificate for a domain. If a CAA record is present, only the CAs listed in the record is allowed to issue TLS certificates for this domain.

You can add a CAA record just for a subdomain. Only Let's Encrypt is allowed to issue certificates for git.ralscha.ch

git.ralscha.ch. IN CAA 0 issue "letsencrypt.org"

Or you can specify the whole domain. Only Let's Encrypt is allowed to issue a *.ralscha.ch TLS certificate.

Gitea also supports Git over SSH. You might be familiar with this when you work with GitHub repositories. First we need to create a key pair on our computer.

ssh-keygen -f e:/gitea_key -N "passphrase" -t ed25519 -C "gitea_key"

Open the Gitea webpage, go to Your Settings -> SSH / GPG Keys.

Under the section Manage SSH Keys click Add Key. Open the public key file on your computer in a text editor. In my example ssh-keygen stored the public file in e:/gitea_key.pub. Copy and paste the public key into the Content text field then click the green Add Key button.

When you followed the steps in my blog post about setting up a VPS, the SSH server only allows the manager user to login. When we want to connect to Gitea over SSH we need to add the git user to the list of allowed SSH users.