Add GitLab Runners
Categories:
Projects:
c2platform/phx/ansible , c2platform.mgmt.gitlab runner
Overview
This how-to describes how to create GitLab Runners on nodes pxd-runner1 and
pxd-runner2 using the Ansible GitLab Runner play. Both nodes are configured
similarly, but pxd-runner2 simulates an air-gapped installation based on a
manual installation variant. This allows testing scenarios where internet
access is restricted, such as downloading packages offline.
GitLab Runners execute CI/CD pipelines for your GitLab projects. In this setup, we provision runners with different executors (e.g., Docker and Shell) to handle various job types securely and efficiently.
Prerequisites
- Setting Up GitLab CE: This guide describes how to provision and configure a GitLab Community Edition instance in the PHX reference implementation.
- Ensure the nodes
pxd-rproxy1,pxd-ad, andpxd-gitlabare up and running.
Setup
To create the runner on the pxd-runner1 node and register it, run the
following command. This takes around 4 minutes to complete:
vagrant up pxd-runner1
Air-Gapped Installation (Optional)
To perform an installation that simulates an air-gapped environment (based on
the manual installation variant), create the pxd-runner2 node. This takes
around 15 minutes to complete:
vagrant up pxd-runner2
Verify
Runners
Navigate to
Groups → C2 Platform → Build → Runners
.
Depending on whether you provisioned pxd-runner2, you should see 4 or 8
registered runners. Without pxd-runner2, there are 4 runners (one each for
Docker and Shell executors in VM and container modes). With pxd-runner2,
this doubles to 8 runners. The image below shows an example with 4 runners.

Git LFS and GitLab Pages
Navigate to Groups → C2 Platform → C2 Platform → Examples → Git LFS and GitLab Pages → Build → Pipelines and start a new pipeline.
Once the pipeline completes, navigate to Deploy → Pages . This page displays the URL to the GitLab Pages website created by the pipeline.

Click on the URL to access the landing page for the Ansible Software Repository.

If you click on the link for apache-tomcat-10.1.19.tar.gz, it should download
the tarball. This demonstrates that the GitLab Runner successfully executed the
pipeline, including publishing a GitLab Pages website that implements a software
repository using Git LFS and GitLab Pages.
GitLab Runner CLI
SSH into pxd-runner1:
vagrant ssh pxd-runner1
Switch to root:
sudo su -
You can now use the GitLab Runner CLI to perform various tasks. For help:
gitlab-runner --help
Show me
For example, list the runners on this node:
gitlab-runner list
root@pxd-runner1:~# gitlab-runner list
Runtime platform arch=amd64 os=linux pid=4060 revision=dcfb4b66 version=15.10.1
Listing configured runners ConfigFile=/etc/gitlab-runner/config.toml
pxd-runner1 Executor=shell Token=btPy-VV2HF2DxVxh1xzM URL=https://gitlab.com/
root@pxd-runner1:~#
Review
Vagrant Boxes
The Vagrant configuration defines two runner nodes: pxd-runner1 and
pxd-runner2. pxd-runner2 includes an additional label for air-gapped
simulation. These boxes use Ubuntu 24 LXD and apply the mgmt/gitlab_runner
play.
Box definition in Vagrantfile.yml:
253 - name: runner1
254 short_description: Gitlab Runner
255 description: Gitlab Runner
256 box: ubuntu24-lxd
257 ip-address: 192.168.60.13
258 plays:
259 - mgmt/gitlab_runner
260 labels:
261 - gitlab_runner
262 - name: runner2
263 short_description: Gitlab Runner
264 description: Gitlab Runner
265 box: ubuntu24-lxd
266 ip-address: 192.168.60.15
267 plays:
268 - mgmt/gitlab_runner
269 labels:
270 - gitlab_runner
271 - gitlab_runner_air_gapped
Play
The Ansible play targets hosts labeled gitlab_runner or
gitlab_runner_air_gapped. It applies core Linux roles and the
c2platform.mgmt.gitlab_runner role to set up the runners.
---
- name: GitLab Runner
hosts: gitlab_runner:gitlab_runner_air_gapped
become: true
roles:
- c2platform.core.linux
- c2platform.mgmt.gitlab_runner
Main Configuration
The main configuration for the GitLab Runner is in
group_vars/gitlab_runner/main.yml. It defines the runner version, coordinator
URL, authentication token, packages to install, group ID, environment variables
(for certificate trust), and disables default runner creation. It also sets up
custom resources like user groups and configuration files for concurrency and
logging.
group_vars/gitlab_runner/main.yml
---
px_gitlab_runner_version: 18.9.0-1
gitlab_runner_coordinator_url: "https://{{ px_gitlab_domain }}"
gitlab_runner_token: "{{ px_gitlab_root_pat }}"
gitlab_runner_package:
- "gitlab-runner-helper-images={{ px_gitlab_runner_version }}"
- "gitlab-runner={{ px_gitlab_runner_version }}"
gitlab_runner_group: 2 # group: c2platform # TODO PHX-548
gitlab_runner_environment:
REQUESTS_CA_BUNDLE: "{{ px_linux_cert_dir }}/c2.crt.crt"
# Disable default runner creation
gitlab_runner_resource_groups_disabled: [default]
gitlab_runner_resources:
0_config:
- name: gitlab-runner # required for vm-runner and shell-exe
module: user
groups: docker
append: true
- name: config.toml & config_template.toml
module: copy
defaults:
mode: '644'
resources:
- dest: /etc/gitlab-runner/config.toml
content: |
concurrent = 1
check_interval = 0
shutdown_timeout = 0
log_format = "text"
force: false
- dest: /etc/gitlab-runner/config_template.toml
content: |
[[runners]]
[runners.docker]
host = "unix:///var/run/docker.sock"
volumes = ["/var/run/docker.sock:/var/run/docker.sock"]
privileged = false
Custom GitLab Runner Image
This configuration builds a custom Docker image for the GitLab Runner that
trusts C2 certificates. It creates a directory, copies certificates and configs,
updates the Dockerfile with the actual Docker GID, and builds the image
(gitlab/c2-gitlab-runner:latest). This ensures runners in container mode can
handle Docker operations securely with proper certificate trust.
group_vars/gitlab_runner/image.yml
---
# GitLab Runner config and GitLab Runner image that trusts C2 certificates
gitlab_runner_resources:
0_gitlab_runner_image:
- name: /opt/gitlab-runner
module: file
path: /opt/gitlab-runner
mode: '755'
state: directory
- name: /opt/gitlab-runner/Dockerfile
module: copy
defaults:
mode: '644'
resources:
- dest: /opt/gitlab-runner/c2.crt
src: "{{ px_linux_cert_dir }}/c2.crt.crt"
remote_src: true
- dest: /opt/gitlab-runner/config.toml
src: /etc/gitlab-runner/config.toml
remote_src: true
- dest: /opt/gitlab-runner/config_template.toml
src: /etc/gitlab-runner/config_template.toml
remote_src: true
- dest: /opt/gitlab-runner/Dockerfile.tpl
content: |
# for container-runner with shell-exe:
# - docker.io package required
# - gitlab-runner in docker group
FROM gitlab/gitlab-runner:latest
ARG DOCKER_GID=999
COPY c2.crt /usr/local/share/ca-certificates/c2.crt
COPY config.toml /etc/gitlab-runner/config.toml
COPY config_template.toml /etc/gitlab-runner/config_template.toml
RUN update-ca-certificates \
&& apt update \
&& apt install docker.io -y \
&& apt clean
RUN if ! getent group docker; then \
groupadd -g ${DOCKER_GID} docker; \
else \
groupmod -g ${DOCKER_GID} docker; \
fi
RUN usermod -a -G docker gitlab-runner
- name: Update Dockerfile with actual Docker GID
module: shell
cmd: |
cat /opt/gitlab-runner/Dockerfile.tpl > /opt/gitlab-runner/Dockerfile
DOCKER_GID=$(getent group docker | cut -d: -f3)
sed -i "s/ARG DOCKER_GID=999/ARG DOCKER_GID=${DOCKER_GID}/" \
/opt/gitlab-runner/Dockerfile
- name: gitlab/c2-gitlab-runner
module: docker_image
tag: latest
build:
path: /opt/gitlab-runner
dockerfile: Dockerfile
pull: true
source: build
state: present
Runners Configuration
This configuration registers multiple runners with specific tags, executors, and settings. It defines tags based on the environment (e.g., hostname, OS), and registers runners for Docker and Shell executors in both VM and container modes. The common registration flags ensure non-interactive setup with the coordinator URL.
group_vars/gitlab_runner/runners.yml
---
gitlab_runner_tag_list:
- px
- pxd
- "{{ ansible_fqdn }}"
- "{{ ansible_distribution | lower }}"
- "{{ ansible_os_family | lower }}"
- "{{ ansible_distribution_version }}"
gitlab_runner_resources:
1_runners:
- name: Register runners
module: gitlab_runner
defaults:
api_url: "{{ gitlab_runner_coordinator_url }}"
api_token: "{{ gitlab_runner_token }}"
environment: "{{ gitlab_runner_environment }}"
active: true
run_untagged: true
locked: false
group: "{{ gitlab_runner_group }}"
resources:
- description: "{{ inventory_hostname }}-docker"
tag_list: "{{ gitlab_runner_tag_list + ['vm-runner', 'docker-exe'] }}"
register: >-
{{ px_gitlab_runner_register_common }}
--executor "docker"
--docker-image alpine:latest
--template-config /etc/gitlab-runner/config_template.toml
- description: "{{ inventory_hostname }}-shell"
tag_list: "{{ gitlab_runner_tag_list + ['vm-runner', 'shell-exe'] }}"
register: >-
{{ px_gitlab_runner_register_common }}
--executor "shell"
- description: "{{ inventory_hostname }}-dind"
tag_list: "{{ gitlab_runner_tag_list + ['container-runner', 'docker-exe'] }}"
container:
name: "gitlab-runner-{{ inventory_hostname }}-docker"
image: gitlab/c2-gitlab-runner:latest
register: >-
{{ px_gitlab_runner_register_common }}
--executor "docker"
--docker-image alpine:latest
--template-config /etc/gitlab-runner/config_template.toml
- description: "{{ inventory_hostname }}-sind"
tag_list: "{{ gitlab_runner_tag_list + ['container-runner', 'shell-exe'] }}"
container:
name: "gitlab-runner-{{ inventory_hostname }}-shell"
image: gitlab/c2-gitlab-runner:latest
register: >-
{{ px_gitlab_runner_register_common }}
--executor "shell"
px_gitlab_runner_register_common: >-
--non-interactive
--url "{{ gitlab_runner_coordinator_url }}"
Air-Gapped Installation
The air-gapped configuration for pxd-runner2 disables the default
installation from the GitLab Runner role and replaces it with a custom
installation method suitable for environments without internet access. This is
defined in group_vars/gitlab_runner_air_gapped/main.yml. It disables the
1_install resource group and introduces 1_install_air_gapped, which installs
DEB packages from a local repository, enables the service, and sets the version
and repository URLs accordingly. This demonstrates the flexibility of the
Ansible role in supporting custom, offline installation variants.
group_vars/gitlab_runner_air_gapped/main.yml
---
# Disable default install from GitLab Runner role
gitlab_runner_bootstrap_resource_groups_disabled: [1_install]
# Configure custom install
gitlab_runner_bootstrap_resources:
1_install_air_gapped:
- name: gitlab-runner-helper-images.deb
module: apt
deb: "{{ px_gitlab_runner_repo }}/gitlab-runner-helper-images.deb"
- name: gitlab-runner_amd64.deb
module: apt
deb: "{{ px_gitlab_runner_repo }}/gitlab-runner_amd64.deb"
- name: gitlab-runner
module: service
enabled: true
gitlab_runner_package_urls:
Debian: "{{ px_gitlab_runner_repo }}/gitlab-runner_amd64.deb"
# https://gitlab.com/gitlab-org/gitlab-runner/-/releases
px_gitlab_runner_version: v18.9.0
# px_gitlab_runner_version: latest
px_gitlab_runner_repo: >-
{{ "https://s3.dualstack.us-east-1.amazonaws.com/gitlab-runner-downloads/"
~ px_gitlab_runner_version ~ "/deb"
}}
See also default install in roles/gitlab_runner/defaults/main.yml in GitLab
Runner role c2platform.mgmt.gitlab_runner:
roles/gitlab_runner/defaults/main.yml
37 1_install:
38 - name: Download GitLab Runner repository installation script
39 module: get_url
40 url: "{{ gitlab_runner_repository_installation_script_url }}"
41 dest: "{{ gitlab_runner_repo_script_path }}"
42 - name: Install GitLab Runner repository
43 module: command
44 cmd: "bash {{ gitlab_runner_repo_script_path }}"
45 changed_when: true
46 # creates TODO
47 - name: "{{ gitlab_runner_package }}"
48 module: package
49 state: present
50 - name: gitlab-runner
51 module: service
52 enabled: true
Additional Information
For further reference, explore the following information:
- Run GitLab Runner in a Docker Container: Manually register and start GitLab Runner in a Docker container for isolation.
- GitLab Runner Official Documentation
- GitLab Runners API
- GitLab Runner Releases
- community.general.gitlab_runner Module
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.