Install a self-hosted Git server with Gitea

Published: June 10, 2018  •  linux, selfhosted

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.


Domain Name

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

git_01

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.

git_02

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.


Install Gitea

On the server install the Git package, which Gitea depends on.

sudo apt install git

Create a new user under which the Gitea process will run

sudo adduser --system --shell /bin/bash --gecos 'Gitea user' --group --disabled-password --home /home/git git

Create the required directory structure. Everything will be installed in the /home/git/gitea directory.

sudo mkdir -p /home/git/gitea/{custom,data,indexers,public,log}
sudo chown git:git /home/git/gitea/{custom,data,indexers,public,log}
sudo chmod 750 /home/git/gitea/{custom,data,indexers,public,log}
sudo chown git:git /home/git/gitea

Download the Gitea binary and make it executable. Check the download page first to figure out the latest version. At the time of writing (June 2018) 1.4.2 is the latest version.

cd /home/git/gitea
sudo wget -O gitea https://dl.gitea.io/gitea/1.4.2/gitea-1.4.2-linux-amd64
sudo chmod +x gitea

Next we need to install Gitea as a service so it will automatically start at boot time when we restart the server. On Ubuntu this is the responsibility of systemd.

The Gitea project provides an example of a systemd service file. Download it and open it in a text editor.

cd /home/git/gitea
sudo wget https://raw.githubusercontent.com/go-gitea/gitea/master/contrib/systemd/gitea.service
sudo nano gitea.service

We have to change the paths on the following lines

WorkingDirectory=/home/git/gitea/
ExecStart=/home/git/gitea/gitea web -c /home/git/gitea/custom/conf/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/home/git/gitea

Save (ctrl+o) and close (ctrl+x) the editor.

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.

sudo ln -s /home/git/gitea/gitea.service /lib/systemd/system/gitea.service
sudo systemctl daemon-reload

You can now start Gitea and check the status.

sudo systemctl start gitea
sudo systemctl status gitea

If everything is okay you should see a green active (running) message. If something is wrong check the log file with sudo journalctl -u gitea.

The service is running but not enabled yet and will not automatically start at the next server start up. Enable it and check if it is enabled

sudo systemctl enable gitea
sudo systemctl is-enabled gitea

The is-enabled command should return enabled.


Update Gitea

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.

sudo systemctl stop gitea
cd /home/git/gitea
sudo rm gitea.old
sudo mv gitea gitea.old
sudo wget -O gitea https://dl.gitea.io/gitea/1.4.x/gitea-1.4.x-linux-amd64
sudo chmod +x gitea
sudo systemctl start gitea

HTTP Server

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.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Open a browser and enter the URL http://git.ralscha.ch. You should see the nginx welcome page.

Now we create a configuration for the subdomain.

sudo nano /etc/nginx/sites-available/git

Add the following configuration. This configuration forwards all request to Gitea which is listening on port 3000.

server {
    listen 80;
    listen [::]:80;
    server_name git.ralscha.ch;


    client_max_body_size 20m;
    location / {
        proxy_pass http://localhost:3000;
    }
}

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.

Enable the configuration, remove the default nginx configuration and reload nginx

sudo ln -s /etc/nginx/sites-available/git /etc/nginx/sites-enabled/git
sudo rm /etc/nginx/sites-enabled/default
sudo systemctl reload nginx

Initial configuration

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

git_03

Under the General Application Settings section change LFS Root Path, Domain, SSH Port. Application URL and Log Path
git_04

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. git_06

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. git_07

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

DISABLE_REGISTRATION              = false

and change it

DISABLE_REGISTRATION              = true

Restart gitea with sudo systemctl restart gitea


First repository

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.

git_08

git_09

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

git clone http://git.ralscha.ch/sr/test.git
cd test
echo Hello World > test.txt
git add test.txt
git commit -m "my first commit"
git push

Visit the repository page in Gitea and you should see the commit. git_10


TLS

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.

sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot

Press Enter

sudo apt update
sudo apt install python-certbot-nginx 

Press y to install the package.

Request a TLS certificate with the following command

sudo certbot --nginx

Certbot first asks for an email address. This is used for urgent renewal and security notices.

Then you have to agree to the terms of services. After that the script asks if it can share your email address with the Electronic Frontier Foundation. Enter n if you don't want to share.

Certbot next lists all installed subdomains in nginx. In our case there should be only one entry. Enter the number 1 to select this domain.

Select "redirect all traffic to https" (enter 2).

As the last step we have to change the URL in the Gitea configuration.

sudo nano /home/git/gitea/custom/conf/app.ini

search for the ROOT_URL line and change it to https

ROOT_URL         = https://git.ralscha.ch/

Restart Gitea with sudo systemctl restart gitea. Open the webpage of your Gitea instance. If you enter the URL http:// the server automatically redirects to https://


CAA

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.

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

Visit the Wikipedia page about CAA https://en.wikipedia.org/wiki/DNS_Certification_Authority_Authorization for more information and examples.

This site provides a useful CAA generator: https://sslmate.com/caa/

Check the documentation of your DNS provider (usually the company where you bought the domain) how to add a CAA record.


Git over SSH

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. git_11

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.

git_12


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.

Open the SSH configuration file sudo nano -w /etc/ssh/sshd_config and add the user git

AllowUsers manager git

Restart the SSH server sudo systemctl restart ssh

Open <user_home>/.ssh/config on your local computer and add a new entry for Gitea. You can choose an arbitrary name for the Host. IdentityFile points to the private key file that ssh-keygen generated.

Host gitea
  HostName git.ralscha.ch
  User git
  Port 44933
  IdentityFile e:/gitea_key
  IdentitiesOnly yes

Now we can test if Git over SSH works.

git clone ssh://git@gitea/sr/test.git
cd test
echo A change >> test.txt
git add test.txt
git commit -m "update"
git push

Open the repository web page and check if you see the commit.

For more information about Git over SSH visit:
https://help.github.com/articles/connecting-to-github-with-ssh/


Backup

There are different ways how you can back up the Gitea installation. Gitea itself provides a built in dump and restore feature.

dump writes all the configuration files and repositories into one zip file. See the official homepage for more information about the built in Backup and Restore functionality: https://docs.gitea.io/en-us/backup-and-restore/

In this blog post you find a tutorial for installing a daily backup job that sends backup files to Amazon S3.