Set up a Private GitLab Runner on Alpine Linux
Updated Tuesday, Jan 9, 2024
GitLab has recently locked down the accessibility to free CI/CD minutes. You now need to provide a Credit Card to prove you’re a human. Apparently cryptofriends were using the CI/CD minutes to mine for cryptocurrencies. Huh… if I had lesser ethics I’d probably do the same thing! Kind of brilliant to be honest. Anyway, the end result is if you want users to contribute to your project they need to either provide a CC or better yet, you can set up private GitLab runners. Just make sure to disable usage of shared runners, or they’ll continue to get the CC nag, and their builds will autofail.
Another reason to use your own GitLab runners is they’ll probably be faster than the shared runners. Additionally if you have private GitLab projects, your CI/CD minutes are numbered.
§BTW - Here’s an Ansible playbook
I wrote a short playbook based off of the steps outlined below. You can check it out here: https://gitlab.com/winny/gitlab-runner-playbook/-/tree/master
§Set up the community repository
Edit /etc/apk/repositories
. Uncomment the line that looks like
http://dl-cdn.alpinelinux.org/alpine/v3.15/community
. This is needed for
installing the needed software.
§Install docker
First you have to install docker and start it up:
apk add docker # Install docker
rc-service docker start # Start the service
rc-update add docker # Start the service on subsequent boots
§Install GitLab runner
Next let’s install the gitlab-runner program. shadow
which contains
gpasswd
which is a simple way to add a user to a group.
apk add gitlab-runner # Install gitlab-runner
apk add shadow # Needed for 'gpasswd'.
Next add the gitlab-runner
user to the docker group.
gpasswd -a gitlab-runner docker
Register the GitLab Runner. You’ll need to specify a default docker image. I
usually do alpine:latest
, but it shouldn’t matter because the image
should
be specified in your .gitlab-ci.yml
for maximum clarity. You will also need
the registration token from your GitLab project’s CI/CD page. You can find it
by clicking on Settings -> CI/CD -> expand “Runners”. This is also where your
runners will be listed.
gitlab-runner \
--non-interactive \
--run-untagged \
--url https://gitlab.com/ \
--executor docker \
--name 'name to identify your runner in the gitlab UI' \
--docker-image alpine:latest \
--registration-token your-registration-token-here
Now fix the permissions. It appears this file is not readable by the gitlab-runner user (though alpine does set this user up to utilize this file - weird!). Let’s change it so it belongs to the gitlab-runner group and is readable by that group:
chgrp gitlab-runner /etc/gitlab-runner
chmod 0750 /etc/gitlab-runner
chgrp gitlab-runner /etc/gitlab-runner/config.toml
chmod 0640 /etc/gitlab-runner/config.toml
Optional, add syslog logging. Add --syslog
to your
/etc/conf.d/gitlab-runner
. The file should look like the following:
# Extra options passed to 'gitlab-runner run'
GITLAB_RUNNER_OPTS="--config /etc/gitlab-runner/config.toml --working-directory /var/lib/gitlab-runner --service gitlab-runner --syslog"
# Change to root if you want to run a system instance instead of a user one
GITLAB_RUNNER_USER="gitlab-runner"
# Same as above
GITLAB_RUNNER_GROUP="gitlab-runner"
Next, let’s start and enable the runner
rc-service gitlab-runner start
rc-update add gitlab-runner
§Now test if it works!
-
Test if the runner is visible on the page where the registration token can be found (Runner settings).
-
Trigger a gitlab CI job with the new runner.
§Troubleshooting
Edit /etc/init.d/gitlab-runner
. Add --debug --syslog
between the “run”
subcommand and the gitlab-runner
program. So the relevant line should look
like this:
command_args="--debug run --syslog ${GITLAB_RUNNER_OPTS}"
Now you can check /var/log/messages
for errors.
§Final remarks
It’s a good idea to use a VM server to deploy a gitlab runner that can use docker. This way you can contain a lot of the security concerns to a single VM guest. You also do not need to expose your guest to the internet or even the local LAN - it only needs to dial out via a NAT.
Another cool thing learned when working on this is one can use the
community.libvirt.libvirt_qemu
connection plugin to manage guests without even
needing SSH access or credentials. This uses the qemu guest agent, bypassing the
need for suitable networking to manage guests.
Stay tuned for more infrastructure posts.