Hosting Gitea on Google Cloud Platform
Tags: git, gcp, gitea
Published: 2019-11-26 18:45:34

This tutorial assumes you already have a registered domain and access to your DNS records. I used Cloudflare, but feel free to use your domain registrar's build in DNS records. This tutorial is heavily based on [this excellent tutorial](https://bryangilbert.com/post/devops/how-to-setup-gitea-ubuntu/) by [Bryan Gilbert](https://bryangilbert.com) with additions specific to Google Cloud Platform and from my own experience.

## Getting Ready

Start by heading to https://cloud.google.com/ and signing up for a free account. Make sure you enter your credit card details to enable full access. Don't worry though, this won't cost us anything.

## Virtual Machine Setup

Once you're in your GCP console, create a new project by navigating to the top left and selecting 'New Project'. The name is unimportant, I chose 'Gitea'. Then, select the project from the same menu. 

Next, open the side menu and navigate to `Compute Engine > VM Instances`. Wait a few minutes for Compute Engine to get ready.

Click `Create`  and setup your vm with the following parameters:

* Machine Type: f1-micro
* Boot Disk: Ubuntu 20.04 LTS with a 30 GB standard persistent disk 
* Firewall: Allow HTTP Traffic, Allow HTTPS Traffic

Here is an [example setup page](https://lh3.googleusercontent.com/DH9v_kq43yOxEOn9nHPkgm6f4jV5mIueJxvax8u7PnrjxTcDISqPjzobaMtC67myiplliFNvzAFr_Fg-DhlBUKPmPRZMdrfULZoKwHuaX3zOjzyPAJsX73TlUwwvOhLXneM_SeKkwBY=w2400)

## Firewall Setup

Open the side menu and navigate to `VPC Network > Firewall rules`.

We will be adding 3 rules to our firewall. This can be done by clicking `CREATE FIREWALL RULE` at the top of the page. They are as follows:

| Rule Name   | Direction of traffic | Targets                      | Source IP ranges | Specified protocols and ports (tcp) |
| ----------- | -------------------- | ---------------------------- | ---------------- | ----------------------------------- |
| gitea-setup | Ingress              | All instances in the network | 0.0.0.0/0        | 3000                                |
| ssh-in      | Ingress              | All instances in the network | 0.0.0.0/0        | 5522                                |
| ssh-out     | Egress               | All instances in the network | 0.0.0.0/0        | 5522                                |

## Connect to the VM

The easiest way to connect to the VM is by pressing the `SSH` button on the `VM Instances` page. This opens up a terminal connected to your VM right within your browser. Viewable [here](https://lh3.googleusercontent.com/1aO7oWSmUqmqTcxzkWqfrVK1bL2g3Vyfs2QwTpwSepZPuz9GOxhNkSkhtbLstBMF9le1QtbSbZKnRCixz-Iz764cHqEHkNgjOqQqPzKEVaWxvF3a-nLt-TcA9-nQRfVMgPx0Li1dTgI=w2400).

## Server Setup

Run the following commands to update and upgrade any packages:

```bash
sudo apt update
sudo apt upgrade
```

Now, we will create a new user named `git` who does not have a password

```bash
sudo adduser --system --shell /bin/bash --group --disabled-password --home /home/git git
```

Now that we have our user, we need to give them "sudo" permissions, so that the account can run administrator commands. This is done by editing the sudoers file as follows:

```bash
sudo EDITOR=nano visudo
```

Now, add the following line to the bottom of the file:

```
git  ALL=(ALL) NOPASSWD:ALL
```

Press `CTRL+X` (`control+X` on MacOS), then `Y`, then `Enter`.

Next, restart the VM for the changes to take effect. GCP calls this `RESET`

## PostgreSQL Setup

Install PostgreSQL:

```bash
sudo apt install postgresql
```

Now, let's switch to the `postgres` user and enter the database

```bash
sudo su postgres
psql
```

Next, we are going to create a database and a user. Make sure you change `<password>` to an actual password:

```sql
CREATE USER gitea WITH PASSWORD '<password>';
CREATE DATABASE gitea OWNER gitea;
\q
```

## Gitea Installation & Setup

Since we are still logged into the postgres user, we have to switch accounts. For the second-last command, we download Gitea. However, the version downloaded might be out of date. Check [here](https://github.com/go-gitea/gitea/releases) for the most up to date release. The version should be listed as 'Latest release'. Then, adjust the command to match the current version number.

```bash
exit
sudo su git
cd /home/git
mkdir gitea
cd gitea
wget -O gitea https://github.com/go-gitea/gitea/releases/download/v1.13.0/gitea-1.13.0-linux-amd64
chmod +x gitea
```

Now we are going to run Gitea for the initial setup.

```bash
./gitea web
```

Open up the Gitea web interface by navigating to your VM's external IP with the port 3000. E.g. http://93.184.216.34:3000

If the install page doesn't appear instantly, press the login button and it will appear.

Change the following accordingly:

* `Database Type`: PostgreSQL
* `Password`: The password you set in the PostgreSQL Setup step
* `Application Name`: Optional, as you please
* `SSH Port`: 5522
* `Domain`: Your domain (E.g. git.example.com)
* `Application URL`: Your domain (E.g. http://git.example.com)

Under `Optional Settings`, open `Server and Third-Party Service Settings` and change the following settings:

* `Disable Self-Registration`: True
* `Allow Registration Only Through External Services`: False
* `Enable OpenID Self-Registration`: False
* `Enable OpenID Sign-In`: False

Finally, setup an admin account by opening `Administrator Account Settings` and filling in the fields.

Click `Install Gitea`

Now, delete the `gitea` firewall rule for security.

## Systemd Service Setup

Next, we are going to setup a service for gitea to run in the background

```bash
sudo nano /etc/systemd/system/gitea.service
```

Paste the following into the file:

```TOML
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=postgresql.service

[Service]
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/home/git/gitea
ExecStart=/home/git/gitea/gitea web
Restart=always
Environment=USER=git HOME=/home/git

[Install]
WantedBy=multi-user.target
```

Enable the service with the following commands:

```bash
sudo systemctl enable gitea.service
sudo systemctl start gitea.service
```

## Nginx Setup

Install Nginx:

```bash
sudo apt install nginx
```

Now, we are gonna sent up Nginx:

```bash
sudo nano /etc/nginx/sites-enabled/gitea
```

Paste the following into the file, changing `<your-domain>` to your domain:

```Nginx
server {
    listen 80;
    server_name <your-domain>;

    location / {
        proxy_pass http://localhost:3000;
    }

    proxy_set_header X-Real-IP $remote_addr;
}
```

Next, remove the default site and reload the service:

```bash
sudo rm /etc/nginx/sites-enabled/default
sudo service nginx reload
```

## Fail2ban Setup

Install Fail2ban:

```bash
sudo apt install fail2ban
```

Setup filter:

```bash
sudo nano /etc/fail2ban/filter.d/gitea.conf
```

```TOML
[Definition]
failregex =  .*Failed authentication attempt for .* from <HOST>
ignoreregex =
```

Setup ban connection with gitea:

```bash
sudo nano /etc/fail2ban/jail.d/jail.local
```

```TOML
[gitea]
enabled = true
port = http,https
filter = gitea
logpath = /home/git/gitea/log/gitea.log
maxretry = 10
findtime = 3600
bantime = 900
action = iptables-allports
```

Finally, restart the service for the effects to take effect:

```bash
sudo service fail2ban restart
```

## Let's Encrypt Setup

Before proceeding, ensure that your DNS records point to the VM's external IP. If not, certbot will fail. Another note, it cannot point to a CNAME record, it has to be an A or AAAA record. Fun fact!

Install certbot:

```bash
sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt update
sudo apt install python3-certbot-nginx 
```

Setup Certbot:

```bash
sudo certbot --nginx
```

## Enable Automatic Certificate Renewal

Create a service to renew the certificate:

```bash
sudo nano /etc/systemd/system/certbot-renewal.service
```

```TOML
[Unit]
Description=Certbot Renewal

[Service]
ExecStart=/usr/bin/certbot renew
```

Next, create a daily timer

```bash
sudo nano /etc/systemd/system/certbot-renewal.timer
```

```TOML
[Unit]
Description=Timer for Certbot Renewal

[Timer]
OnBootSec=300
OnUnitActiveSec=1d

[Install]
WantedBy=multi-user.target
```

Now simply start and enable the timer:

```bash
sudo systemctl enable certbot-renewal.timer
sudo systemctl start certbot-renewal.timer
```

## Enabling Git Over SSH

Now that we're done with the command line, navigate back to your Gitea website, now hosted on your domain (E.g. git.example.com).

Click the profile icon in the top right and go to `Site Administration`

Run the `Maintenance Operation` titled 

```
Update the '.ssh/authorized_keys' file with Gitea SSH keys. (Not needed for the built-in SSH server.)
```

## Done

Enjoy!

Maybe create a user account and don't use the admin one. This is also done in the `Site Administration` section.


Thank you again to [Bryan Gilbert](https://bryangilbert.com) and I hope you enjoyed.