My crude Raspberry Pi stack.

What am I reading?

This is a guide which will show you how to use two Raspberry Pi 3's to run GitLab CE. One Pi will run Redis, postgresql and nginx; the other will run the remaining required services. This guide is not a practical business solution. The cluster should not be run for long periods of time and I do not cover security thoroughly. This is great for having a portable backup of your git repositories, learning about GitLab CE and Raspberry Pi or just for fun.

Last year I setup GitLab CE on a Raspberry Pi 3 to see how it would run. As I expected - it was terribly slow. The main issue was the web interface, with response times exceeding 30 seconds on almost all requests. Running git from the terminal was quick and transfer speeds were great since it was all on the local network. Because of GitLab's excellent documentation and easy-to-use configuration, I knew that adding a 2nd Pi to the mix would not be too tough. The results were great, I have not noticed any hang-ups and response time is consistently 1 - 2 seconds.

Before you start make sure you have the following
  • 2 - Raspberry Pi 3
  • 2 - Micro USB power supply (5V/2.5A, avoid using USB ports to power Pi)
  • 2 - Micro SD, recommend minimum of 16GB
  • Ethernet cable, the shorter the better
  • HDMI cable and a screen to connect it to
  • USB Keyboard
  • Internet connection through Wi-Fi

Getting Started

This section is a quick refresher on how to install Raspbian and get started with the Pi. If you have already done this feel free to skip a bit.

Install Raspbian

First you need to install the operating system, Raspbian, on both Micro SD cards. There are very clear instructions on the official Raspbian pages and installations may change in the future so I will simply link to those pages.

  1. Download the Raspbian Stretch Lite image from the official Raspbian page.
  2. Follow the official installation instructions to write the image to both Micro SD cards.

After installing Raspbian, insert the SD card, connect your keyboard and screen, and finally plugin the power. After the boot process finishes, login with the default credentials pi and raspberry. It is recommended to change your default password using the passwd command.

Connect to Wi-Fi

You will need internet access in order to install the required packages. The proper way to do this is through the /etc/wpa_supplicant/wpa_supplicant.conf file. If you are using an older version of Raspbian this may not work. If you have any issues check out this page.

# edit file with desired text editor
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

Add the code below to the end of this file and edit the appropriate values.

network={  
    ssid="YOUR_WIFI_NAME"
    psk="WIFI_PASSWORD"
}

Reconfigure the wlan0 interface.

wpa_cli -i wlan0 reconfigure

You should now be online, let's find out.

curl ifconfig.io
# this should return your ip address

Enable SSH

This step is not necessary but it will remove the need to be connected to a screen by allowing you to access the Pi remotely. This may be necessary if you only have one screen or it can be done for convenience. If you SSH into the Pi from the same computer you are reading this page, you can quickly copy and paste commands or config text.

sudo raspi-config
# select "Interfacing Options" then "SSH" and finally "<Yes>"
SSH will only work if your computer and Pi are connected to the same network.

If you are unfamiliar with SSH there are plenty of great tutorials on the internet. The general idea is that you access the Pi's terminal from a separate device. If you are running Linux chances are you already know how to use the ssh command; if running Windows I would recommend using PuTTY.

Setup web-server Pi

Start with whichever Pi has less disk space, this will be your web-server.

Install nginx

You will need to manually install a web-server, GitLab uses nginx by default and is lightweight so it is a logical choice.

# update packages then install nginx
sudo apt-get update
sudo apt-get install nginx

Wifi IP addressLet's make sure the web-server is up and running, try accessing your Pi from a browser. Navigate to your Pi's Wi-Fi address (from the same network of course), you should see a short welcome message. If you are having problems try rebooting and check out raspberrypi.org for potential updates to nginx installation.

ifconfig
# look for "wlan0" and under that find "inet ip_address"

Configure nginx

You will need to tell nginx to communicate with your other Pi for handling requests. To do this you need to change some configuration in nginx. Copy this config text into /etc/nginx/sites-enabled/gitlab. If you decided to use SSL or a web-server aside from nginx - this page has more config files.

sudo nano /etc/nginx/sites-enabled/gitlab

Insert the nginx config text and make a couple edits to it.

# nginx can not use a unix sock
upstream gitlab-workhorse {
    server 192.168.1.1:8181;
}
# this should match /etc/gitlab/gitlab.rb external_url
server_name gitlab.local.com;

Now you need to delete the default nginx configuration.

sudo rm /etc/nginx/sites-enabled/default

Setup Static Ethernet

You will be connecting the two Pi's via an Ethernet cable, you do not have to plugin the cable yet but you can still setup the Pi to use a static IP for Ethernet.

# open in text editor of your choice
sudo nano /etc/dhcpcd.conf

Add and save the following to the end or beginning of the file.

# static ethernet connection
interface eth0
static ip_address=192.168.1.2/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

Install GitLab CE

Okay, now you can finally install GitLab CE. Once again there are perfectly clear instructions on the official GitLab CE page, please follow steps 1 and 2. You will not need to install postfix, unless you wish to play around with email notifications.

Manual Installation

If you have issues with the gitlab-ce package not being found, you can download the package directly from here. Select the latest version and then run the wget command shown on the package page. After that is complete you can then install the package you have downloaded using dpkg.

# replace "VERSION" with the latest version number
sudo wget --content-disposition https://packages.gitlab.com/gitlab/raspberry-pi2/packages/raspbian/jessie/gitlab-ce_VERSION-ce.0_armhf.deb/download.deb
sudo dpkg -i gitlab-ce*.deb

Configure GitLab CE

You need to setup GitLab to run only the required services. You can either uncomment and edit each of the values below in the default config file or you can just copy this config into the beginning of the file.

# open in text editor of your choice
sudo nano /etc/gitlab/gitlab.rb
# must be the same as other Pi
external_url "http://gitlab.local.com"

# only main GitLab server should handle migrations
gitlab_rails['auto_migrate'] = false

# enable postgresql
postgresql['enable'] = true
postgresql['listen_address'] = '192.168.1.2'

# allow the other Pi to connect to postgresql
postgresql['custom_pg_hba_entries'] = {
    TCP_HOST: [{
        type: 'host',
        database: 'all',
        user: 'gitlab',
        cidr: '192.168.1.0/24',
        method: 'trust',
        option: ''
    }]
}

# enable Redis
redis_master_role['enable'] = true

# setup Redis TCP support
redis['bind'] = '192.168.1.2'
redis['port'] = 6379
redis['password'] = 'your-redis-password'

Save and reconfigure.

sudo gitlab-ctl reconfigure

At this point you can shutdown the Pi and move on to setting up the next Pi.

Setup main GitLab Pi

Follow the previous sections to install Raspbian, connect to Wi-Fi and setup SSH (optional). If you downloaded the package manually on the 1st Pi you can avoid downloading it again by using scp to transfer the file locally.

Setup Static Ethernet

This Pi will also need a static Ethernet address, same process as before but the IP address is different.

sudo nano /etc/dhcpcd.conf

Add and save the following to the end or beginning of the file.

# static ethernet connection
interface eth0
static ip_address=192.168.1.1/24
static routers=192.168.1.2
static domain_name_servers=192.168.1.2

Increase Swap Space

GitLab will need more than 100MB of swap-file space, which is the default on Raspbian. Edit /etc/dphys-swapfile with text editor of your choice.

sudo nano /etc/dphys-swapfile

Find the line #CONF_SWAPSIZE=100 and change it to CONF_SWAPSIZE=4096. This will give you 4GB of swap space. Swap memory is tough on the SD card life-span. If you are using GitLab a lot, I would look into setting up your swap memory to use a flash drive.

Raspberry Pi's connected with ethernet cable.

Connect Devices

It is time to connect the two Raspberry Pi's to each other so that your main GitLab Pi can communicate with the web-server Pi. Connect your Ethernet cable and then do a reboot to restart services. At this point you should plugin your web-server Pi, if it is not already on. If it is I would recommend rebooting that device as well.

# restart the device
sudo reboot

Install & Configure GitLab CE

Follow the previous section on installing GitLab. Once again, we are only doing steps 1 and 2.

Next you will need to configure some addresses and disable some services. You will be editing /etc/gitlab/gitlab.rb again.

# setup an easy to remember and easy to type url
external_url "http://gitlab.local.com"

# GitLab will need to trust our web-server
gitlab_rails['trusted_proxies'] = ['192.168.1.2']
web_server['external_users'] = ['www-data']

# our other pi will run database
gitlab_rails['db_host'] = '192.168.1.2'

# our other pi will also run Redis
gitlab_rails['redis_host'] = '192.168.1.2'
# enter a random password for Redis, we will set the password later
gitlab_rails['redis_password'] = 'your-redis-password'

# Apache does not support UNIX socket so we must enable TCP, our web-server will use this service
gitlab_workhorse['listen_network'] = 'tcp'
gitlab_workhorse['listen_addr'] = '192.168.1.1:8181'

# Now lets disable some services that our other Pi will handle
postgresql['enable'] = false
redis['enable'] = false
nginx['enable'] = false

Save that file and reconfigure GitLab. Make sure both Pi's are running before reconfigure or you will get an error.

sudo gitlab-ctl reconfigure

Start up GitLab CE!

If everything went well, navigate to your web-server Pi's Wi-Fi address and you should see a GitLab page asking for a password. This will be the password for the root account. After setting the password, login with root. If you get a 502 error, try waiting for a minute for the GitLab services to start and then refresh. If you get a 500 error, there is a good chance that something has gone wrong in the configuration, please review the previous steps to make sure everything is correct.

GitLab sign-in screen

Access via URL

If you want to get fancy, you can set things up to use the external URL set in the GitLab configuration file. You need to do two things; first setup the web-server Wi-Fi address to be static and second setup your computer to resolve the local domain.

First you should make the Wi-Fi IP address static so GitLab is always reachable at the same address. You may need to adjust these addresses depending on your router.

# edit with text editor of your choice
sudo nano /etc/dhcpcd.conf

# add the following to beginning or end of file, then close and save
interface wlan0
static ip_address=192.168.1.157/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.1

# reboot to restart network services
sudo reboot

Now you need to tell your computer to use this address whenever a specific domain is accessed. Arguably the easiest way to do this is with a proxy. If you are on Windows you may instead edit the hosts file and add the entry 192.168.1.157 gitlab.local.com. I will show how this can be accomplished using a simple Firefox add-on (I am sure Chrome has a similar add-on). Install the FoxyProxy add-on and then follow the graphic below.

Setup FoxyProxy

Security

I will not cover this in detail but wanted to mention some security measures that should be taken if you want to use this for more than just fun.

GitLab Pi

Ideally this Pi should be cut off from external control. I would at least disable Wi-Fi so nobody can simply access the Pi through the local network. It would be even better to also disable SSH, so the only way to login would require you to physically be at the device.

Web-server Pi

This Pi must be connected to the local network so you should make access credentials more secure. If you have not already, change the default login password using the passwd command, generate a random password and store it in a password manager. Make sure your Redis password is strong. Set a strong password for the gitlab user on the GitLab Pi and then require password within gitlab.rb (postgresql['custom_pg_hba_entries'] setting).

Useful Links

Official Gitlab repository
Official Omnibus GitLab documentation
Maintenance commands
Using a non-bundled web-server
Using a non-packaged Redis instance
Using a non-packaged PostgreSQL database management server

March 4th 2018

Nicholas Horlocker

raspberry pi, devops, gitlab