ARM your continuous integration system with fruits!

11 minute(s) read

ARM your continuous integration system with fruits! 🍌

The goal of this howto is to show you how to add your own ARM Gitlab runner to your Gitlab instance Runners herd.

Let me introduce quickly the concepts.

Continuous integration with Gitlab

Continuous integration allows the developers on a project to check that each change they made did not introduce any regression. Each commit will be followed by a build of their application, and by a run of their test suite. If every test runs still the same way after the commit, then all is fine.

Gitlab is a web-based Git repository manager (with tons of features). You can use it directly on-line, install your own community-edition copy, or pay for top level support.

Today, we’ll be only interested in their continuous integration feature.

Gitlab CI/CD logo

Starting Continuous Integration (i.e. CI) is really straightforward with Gitlab. Just create a .gitlab-ci.yml file in your repository hosted in Gitlab, populate it with the commands needed to build your application, and you’re good to go!

But wait… Where does that build and test execute? That’s where the runners enter.

Runners are machines linked to Gitlab that will execute the builds. These can be real machines, virtual machines or containers. By default, you have access to shared runners on, or even on your company Gitlab instance.

These runners are tagged so that you can also tag your builds accordingly. If you need a runner that will build a Docker image, it could be tagged docker for example, and so would be your build step in your .gitlab.yml file.

Your builds can now easily be customized without ruining your own machine configuration… and even use Docker.

Why would you add a Runner?

If you are using the main Gitlab shared instance, chances are that you will have to be patient to get the results of your build. The Shared Runner concept is really cool, as it allows to share the load, but… you’re not alone waiting in that queue… And the same could be true for your company’s Gitlab instance, as it will soon become popular. So you could add your own machine to the Gitlab Runners herd, just for your project. Pretty neat if you’re tired to wait for other people builds to finish.

The problem is a new machine is not cheap. That’s way cool to have your own Gitlab Runner running in your office, but have a quick look at your pockets contents. Do you have enough cash to buy a new machine? Maybe not…

But wait… In the introduction, I was talking about ARM Runners. Why would you need to add an ARM processor machine as a Gitlab Runner?

If your code does not depend on a specific family of processors, there is no other cheaper alternative to build a new Gitlab Runner.

$15 for an OrangePi Zero machine able to run Docker and Gitlab Runner can’t be beaten.

And… if you want to develop for that kind of architecture (ARMV7, aarch64…), you will need that kind of runner.

I am trying to port software to the ARM processor, and these ARM Gitlab Runners have proven to be really useful. I can develop on my favorite IDE (on a X86 machine for example), commit, and automagically, my modified code will be compiled and tested on an ARM machine.

I have to admit all of this could also be done with X86 Runners, as QEMU is able to emulate ARM processors. And even the build of ARM Docker image can be done on X86 Gitlab Runners, thanks to the amazing work of guys at

But where’s the fun?

And furthermore… We all have a Raspberry Pi taking layer after layer of dust. Who has not been bored after having his first led blink?

Why not put it back to work?

Let’s go then for a cheap and fun solution.

Choose your preferred fruit

Pi Zero, image by OrangePi

In this article, we’re not going to install Gitlab Runner on an Orange Pi, but on a Raspberry Pi (because we had one laying around), but this should work on any fruit (aka ARM Docker capable device), as Banana Pi or Orange Pi.

Raspberry Pi found on Amazon

Pi M1

This version of Gitlab Runner we’ll use needs Docker, that’s why we need a Linux distribution which supports Docker.

We’re using an Hypriot distribution because of the Raspberry Pi. We could have used Raspbian, but HypriotOS is the best Docker-oriented distribution for the Raspberry Pi. From downloading the image to the first docker command will take only five minutes.

There is also a 64bits fork (as lots of Raspberry Pi distributions are not available for 64bits, that’s a nice plus).

To me, that’s the first choice if you want to use Docker on a Raspberry Pi out of the box.

For all other devices, prefer Armbian if supported (like the Orange Pi Zero that can run as a Gitlab Runner too). It’s really easy to install Docker on this distribution.

First of all, let’s download the latest Hypriot distribution.

Downloading and installing the Hypriot Distribution

Go to the Hypriot download page and choose the latest distribution.

On Windows

Next go to your Download folder and extract the downloaded zip file by right-clicking on the file and then clicking on 7-zip -> extract here…. if you use 7-zip. Whatever your unzipping tool may be, right-click and choose the right option to uncompress the file.

After 7-zip is finished with extracting you will have a file with a .img extension.

On OsX

It’s almost the same as for Windows, except that the tool could be Keka.

On Linux

Just use 7z.

Writing the image

In the next step we will flash this file onto your SD card.

We have to use the finest piece of sofware able to write CORRECTLY and CHECK the written image (i.e. Etcher) on any platform. Current version is 1.4.4.

Too bad it does not exist for armv7.

I do insist on the use of Etcher, because lots of supposed Linux bugs are because of a badly written image, or to a faulty SDCard. Etcher will take care of these issues.

If possible, do not use any USB Dongle or gizmo to host the SDCard, prefer your laptop own SDCard reader. And for the SDCard, prefer a REAL and GENUINE SDCard.

How can you differentiate a real one from a bad copy? Well, you can’t, or not easily…

Anyway, unzip the image, and write it with Etcher to your SDCard. In the latests versions of Etcher, you don’t even need to unzip the image file beforehands.

Etcher process

Upon completion, close Etcher and eject the SD card before removing it from its slot. In order to eject the SD card, use the secure eject function in the menu next to your system clock. This is usually in the very bottom right corner of your screen.

Eject SDCard

Now it’s time to start your Raspberry Pi with the SD card

Boot your Raspberry Pi

  • Connect the Raspberry Pi to your local network via an ethernet cable
  • put the SD card into the designated slot
  • plug in the power adapter

After finishing the last step your Raspberry Pi will boot and the LEDs should start blinking. The very first boot will take one to three minutes as the file system will be resized.

Find its IP on the network

After booting, you can find the Raspberry Pi at your network with a simple ping black-pearl.local — no more searching for IP addresses required thanks to the integrated Avahi service discovery.

First SSH

See Github

As you can see in the following ifconfig command, the MAC Address of the Raspberry always starts with B8. That could prove useful if ever this first method does not work.

if config

See Github

So, what shall we do if the very first ping/ssh does not work with black-pearl? Well, as the Raspberry Pis MAC Address always start with B8 we can use nmap and keep only the IPs whose attached MAC Address sport a B8(yes, it’s gross).

If your network starts at 10.XX.30.XX and ends at 10.XX.50.XX, ip_start would be 30 and ip_end would be 50.


See Github

This will give you a list of Raspberry IPs on which you will then be able to try to connect with

SSH Pirate

Machine name and user password

The default user “pirate” (password “hypriot”) can be changed or removed before the first boot. Everything happens in /boot/user-data. You can add your public SSH key, disable password logins and specify a different user account before booting your Raspberry Pi. WiFi can be customized and enabled to have Docker up and running through the air without attaching a keyboard and monitor. How cool is that?

You can also change the name of the machine later on with sudo raspi-config. The changes will have to be made in Network Options/hostname.

Raspi config

Once it’s done, reboot and enjoy your new machine name:

SSH Pirate 2

See Github

Proxy settings

If you have to work behind a corporate proxy, you will have to set a few things before being able to update your machine and run Docker.

Package manager

Edit /etc/apt/apt.conf.d/10proxy and add your proxy (create it if it doesn’t exist yet):


See Github

A sudo apt-get update should prove that the configuration is working

APT Get Update

See Github

While you’re there, update the machine with sudo apt-get upgrade to have the freshest Docker environment available.


If you try to download a Docker image with docker pull … it will fail because Docker doesn’t use the same proxy settings as apt.

Docker compose

See Github

So you will have to create a few directories and files to let Docker know it should use your proxy:

Mkdir sudo vi

See Github

/etc/systemd/system/docker.service.d/https-proxy.conf will contain:

Docker service

See Github

The http version of this file will have the same proxy settings (just remove the S of HTTPS).

Once you’re done with the modifications, you will have to tell Docker to restart to take this into account:


See Github

Then you’ll be able to check that your modifications are correct:

SystemCtl Show

See Github


Check that the date on your machine is correct by issuing date in the terminal. If it’s not correct, you will have some troubles with getting a Docker image.

So, if the date/time are not right, you can set them up with:


See Github

Gitlab Runner

You already know Gitlab Runner, I’m sure you are already using some shared runners with your CI on your company’s gitlab.

Most of the time, you don’t need to setup your own, but as there aren’t that many ARM gitlab runners for the time being…

Gitlab Runner has been ported to ARM last year by Mauricio Ugaz as there wasn’t any available, and everyone needs gitlab-runner on Docker running on ARM, am I right?

Note: there are two versions available. Alpine and Ubuntu. As Alpine is the default image, when you run docker pull klud/gitlab-runner Alpine version will be downloaded.

About the image

This image is built for ARM devices, based on the official repo of the GitLab Runner. That’s a fantastic work that made my daily work really more enjoyable.


Runner container setup

You need to mount a volume into the gitlab-runner container in order to share the configuration. This could be done this way:

Docker Run

See Github

As we want to use the Docker executor, it is necessary to mount the Docker socket this way. Don’t forget to create /etc/gitlab-runner directory ahead of time:

Docker Run2

See Github

Register runner

Once the container is up and running, you can then register the runner on your GitLab server.

Go to your project on your Gitlab instance, click on Settings, then on CI/CD, and click on Expand next to Runner settings.

Scroll down to Setup a specific Runner manually, and note the information regarding the URL and the token.

Use the following registration token during setup: the_token_that_is_yours_and_yours_alone


So once you have the information you need (URL and token), you can then do this:

Docker exec

See Github

Let’s check if this new runner can now be seen. Refresh your CI/CI settings, expand Runner settings, and go down. You should now be able to see your brand new Gitlab-ci runner proudly sporting its ARM tag!

Runner settings


You could also do it this way:

Docker Exec 2

See Github

So now you have your own ARM runner, ready to work.


If you’re going to build images on this runner you can use the standard multi-arch Docker image, because it now has the armv6 binaries in it now (it used not to be the case until 18.0.2). Dockerfiles and info about Docker in Docker images for ARM for earlier versions are here.


In case you’re using docker in docker in the runner, you may experience some issues

Docker Daemon

See Github

So in order to address this issue you need to look within the config folder you mounted in the runner container. There is a config file which is/etc/gitlab-runner/config.toml. You need to add two lines (regarding the privilegedand the volumes)and then restart the runner with docker restart arm-runner.

If you can’t find the file, it is maybe in ~/.runner/config.toml/; copy it in /etc/gitlab-runner after editing it and restart docker.

Config Toml

See Github

So now you can enjoy your first ARM Gitlab build!

First build

Next step, make your Runner available for any project!

Written by

Bruno Verachten

Father of two, husband of one, geek in denial, fond of handheld devices since 1989 and permie. #Linux #Android #Docker #ARMV8 #IOT