Setting up a Gitlab Server on a Raspberry Pi 4
Tags: raspberrypi, gitlab, learning
Published: 2024-04-22 23:05:41

## Preamble
My initial plan was to set up the GitLab server in docker on the Raspberry Pi mainly for portability as I would be setting up different tools and had no plans to add resources to the Pi. However, I ran into some problems. I'm not particularly equipped to resolve them now (believe me I tried) but I intend to retry this sometime in the future. Perhaps some of those issues would be resolved by then (such as an available GitLab docker image that runs on Pi 4 on 32-bit Debian/buster).

Please read my [initial post](https://dev.to/beretests/the-start-of-my-devops-personal-projects-journey-38pa) to understand why I chose Raspberry Pi as the server host. 

## Setup Steps
The steps to complete the setup are outlined below. Expand each step (by clicking on it) for details.

**Install screenshot on the Pi**
I needed a way to take screenshots on the Pi to record the actions to complete the setup. I found the recommendations on [this page](https://www.tomshardware.com/news/raspberry-pi-capture-scre
enshots,40276.html) helpful. I went with installing _Gnome Screenshot_. It's not as intuitive as simply tapping Cmd + Shift +4 on a Mac but it does the job.
 
**Network Setup**
I'm on a standard home network with a simple router and the connecting devices - the Pi, a few laptops a TV, etc (you get the drift). The router assigns IP addresses to the devices via DHCP. All devices on the network have the same public IP address so I had to ensure that all requests to the GitLab server would go to the Pi. I'll outline the steps taken to achieve this.


</br>
**DISCLAIMER:** _This was a bit of head-scratcher for me given I'm no networking guru. It was a huge relief when I finally got it working. I also got to enhance my understanding of how networks work so yay!_</br>

</br>

</br>
- _Edit DNS configuration on the router_

Given that the public IP address assigned by the router was not static, I needed to mitigate the issue of loss in connectivity to the server if/when it changed. Luckily, DNS for my hosts is managed in Cloudflare and they have [a few options](https://developers.cloudflare.com/dns/manage-dns-records/how-to/managing-dynamic-ip-addresses/) for this.</br>
I chose to use DNS-O-Matic by going to the link from the Cloudflare page linked above and following the subsequent setup instructions.

- _Set the private IP address on the Pi to static_

The IP addresses assigned to the devices by the routers have set lease periods so the Raspberry Pi's IP address would change at given intervals. This was not ideal for my desired setup because I needed a stable way to direct traffic to it (the Pi). This was easily resolved by setting the private IP address to `fixed` or `static` in the router so that it never changes. Different routers have different ways to do this so I'll not provide details.


- _Enable port forwarding on the router_

(_Welcome to the most head-scratchy part of this!_)
By default, the router is set up to block all incoming connections to the devices. It was necessary to enable port forwarding from the router to the Pi. In summary, this is opening one or two ports (I opened 2) on the router and directing all connections from that port to a port on the Pi. The exact way to do this varies from router to router so I won't get into detailed steps here but I found the following links useful (they are a little old but still useful, I found):

https://www.computerhope.com/issues/ch001201.htm
https://nordvpn.com/blog/open-ports-on-router/

**Install gitlab server accessible on HTTP**
In the previous step, I did not open the standard ports 80 and 443 for HTTP and HTTPs because I still plan to install other services accessible on the web. This [Wikipedia article](https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers) has a list of available ports - in total, there are 65,535. In addition (and I could be wrong here), using a different port provides an additional layer of security since bad actors typically send bad requests to known ports.
</br>
**FUN FACT:** _I once worked with an older engineer who was often miffed at how unimaginative the requests sent by bad actors were. He would be even more upset that those requests were sometimes successful implying that sysadmins were not doing enough to mitigate known vulnerabilities. I enjoyed working with him and learned a lot from him._
</br>
To install the GitLab server, I followed the steps outlined in the [GitLab installation guide for the Raspberry Pi](https://about.gitlab.com/install/#raspberry-pi-os) (thanks, GitLab for the easy-to-follow instructions). I skipped the step to install `postfix` since I already had an account with Zoho mail.
</br>
On the first few tries of running the installation, it failed because LetsEncrypt, which is enabled by default, could not create the required TLS certificates to run on HTTPS as I had set the `EXTERNAL_URL` similar to `https.gitlab.<site-name>.com`.
</br>
This is when I decided to set the server as accessible on HTTP. The SSL configuration was then completed in the next step.
Given the number of installs I ran, I created a simple bash script for subsequent reruns instead of entering single commands multiple times. 

```bash
#!/bin/bash

# Install and configure the necessary dependencies
sudo apt-get install curl openssh-server ca-certificates apt-transport-https perl
curl https://packages.gitlab.com/gpg.key | sudo tee /etc/apt/trusted.gpg.d/gitlab.asc

# Add the GitLab package repository
sudo curl -sS https://packages.gitlab.com/install/repositories/gitlab/raspberry-pi2/script.deb.sh | sudo bash

#  install the GitLab package
sudo EXTERNAL_URL="http://gitlab.<site-name>.com:<port-number>" apt-get install gitlab-ce
```
I then made the file executable by running `sudo chmod +x filename`.

The GitLab server was then successfully installed (finally!) with the following displayed: 
![Screenshot of Success message of Gitlab server install](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vku1wf6a132a2nqmjgjo.png)

A quick visit to the URL confirmed this and I could log in with the root password located at `/etc/gitlab/initial-root-password`, and change that password via the [provided instructions](https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password).


**Setup acme-dns-certbot to run the server on HTTPS**
To enable HTTPS and avoid opening port 80 to allow LetsEncrypt to create the required certificates, I opted to set LetsEncrypt to use the `dns-challenge` type as opposed to the `http-challenge` commonly used (more details on [challenge types](https://letsencrypt.org/docs/challenge-types/)).

I'm using Cloudflare to manage DNS and LetsEncrypt has detailed instructions on how to set this up so I won't go into details on how I did this but I'll add the links:

- [Install snap](https://snapcraft.io/docs/installing-snap-on-raspbian)
- [Install certbot](https://certbot.eff.org/instructions?ws=nginx&os=debianbuster&tab=wildcard)
- [certbot-dns-cloudflare setup](https://certbot-dns-cloudflare.readthedocs.io/en/stable/)

On completion of this setup and getting the certificates for my site, I then changed the following in the config file located at `/etc/gitlab/gitlab.rb` 

```
nginx['ssl_certificate'] = "<path-to-fullchain-cert>"
nginx['ssl_certificate_key'] = "<path-to-key>"
nginx['redirect_http_to_https'] = true
external_url = "https:gitlab.<site-name>.com:<port-number>"
letsencrypt['enable'] = false
```

I then ran `sudo gitlab-ctl reconfigure`.

The server was then available at the new HTTPS URL (I had to wait a few minutes after the command run completed) which I confirmed in the screenshot below. Root login also worked as before.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/doupekefu2dwum3voode.png)

**Change SMTP Settings**
This initial setup's final step was configuring SMTP since I skipped the `postfix` install step during installation. As usual, the [documentation](https://docs.gitlab.com/omnibus/settings/smtp) provides handy examples for this so I just changed the settings in `/etc/gitlab/gitlab.rb` following the [Zoho example](https://docs.gitlab.com/omnibus/settings/smtp#zoho-mail) in the docs and ran `sudo gitlab-ctl reconfigure` again.

##Next Steps
There are several ways to configure the GitLab server as can be observed in the [config template](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template). For the next step, I plan to configure it to store objects and uploads in Cloudflare's R2 (S3-compatible) storage which is currently free for up to 10G/month (please Cloudflare, don't make us start paying for this!). After that, who knows? I'll take each day as it comes and ensure I document the config changes as I go along.

##Other Takeaways
I found it was necessary to uninstall the GitLab server between installation failure attempts. I found helpful [instructions](https://www.sindastra.de/p/798/how-to-uninstall-gitlab) which I put in a simple (and eventually executable) script.

```bash
#!/bin/bash

# uninstall from gitlab-ctl
sudo gitlab-ctl uninstall
sudo gitlab-ctl cleanse
sudo gitlab-ctl remove-accounts

# uninstall with package manager 
sudo dpkg -P gitlab-ce

# delete associated directories and files
sudo rm -rf /opt/gitlab*
sudo rm -rf /var/opt/gitlab*
sudo rm -rf /etc/gitlab*
sudo rm -rf /var/log/gitlab*

# remove the entries from your apt sources
sudo rm /etc/apt/sources.list.d/runner_gitlab-runner.list*
sudo rm /etc/apt/sources.list.d/gitlab_gitlab-ee.list*
sudo rm /etc/apt/sources.list.d/gitlab_gitlab-ce.list*
```

In the course of uninstalling Gitlab, I encountered some issues with removing some `apt` repos but this [StackOverflow answer](https://raspberrypi.stackexchange.com/a/74255) helped me resolve that.

I hope you find this useful. Feel free to leave a comment to let me know your thoughts, thanks for reading!