Deploying a GitLab Runner on a Raspberry Pi Cluster
A Raspberry Pi cluster can provide a compact, inexpensive pool of build agents for GitLab CI/CD. It is well suited to compiling lightweight applications, running test suites, producing ARM container images, and automating infrastructure tasks without consuming a developer workstation or a larger cloud instance.
The setup involves more than installing the runner package. Reliable results depend on consistent operating systems, a predictable network, suitable executor choices, secure registration, and a workflow that respects the modest CPU, memory, and storage resources of single-board computers. For Australian teams, local power costs, NBN upload performance, and the availability of compatible Pi hardware also affect the design.
Why a Pi cluster suits continuous integration
A cluster made from Raspberry Pi 4 or Pi 5 boards gives GitLab several independent workers. Jobs can run concurrently, while tags direct particular workloads to runners with the right architecture or installed tools. ARM64 support is now common across Alpine, Debian, Ubuntu, .NET, Go, Node.js, and many container images, making the platform useful for modern development pipelines.
The cluster is especially practical for repeatable, low-risk work: linting, unit tests, documentation builds, static analysis, and packaging. It is less suitable for large x86-only projects, heavy virtual machines, or long compilation jobs that require substantial RAM. A mixed fleet can solve that limitation, with Raspberry Pis handling ARM-native tasks and a cloud or workstation runner processing demanding builds.
A Pi cluster also has operational value. It consumes little space and can be hosted in a home office, lab, or small business rack. At Australian electricity prices, its low idle consumption is attractive compared with leaving a desktop or server running around the clock.
Select hardware and network foundations
Use identical boards where possible. Four Raspberry Pi 5 units with 8 GB RAM provide a more predictable pool than a mixture of old Pi 3 and Pi 4 models. Each node should have a reliable USB-C power supply, active cooling, and a case that allows airflow. A powered network switch and short, labelled Ethernet cables are preferable to Wi-Fi for build traffic.
Booting from high-endurance microSD cards is convenient, but SSD storage connected through USB 3 generally offers better durability and faster dependency caches. Keep the operating system on each node and store large build artefacts in GitLab, an object store, or a dedicated NAS rather than filling local disks.
The Australian retail market can be uneven: Core Electronics and Jaycar commonly stock Pi accessories, while board availability and pricing can change quickly. Purchase matching power supplies and storage at the same time, and check that cooling hardware fits the exact Pi generation. In Sydney or Brisbane, warm rooms and summer heat make active cooling particularly worthwhile.
Prepare a consistent operating system
Install a 64-bit distribution on every worker, such as Raspberry Pi OS Lite 64-bit or Ubuntu Server ARM64. Give each node a fixed DHCP lease or a reserved address, then set clear hostnames such as runner-pi01 and runner-pi02. Consistency matters because a pipeline that passes on one worker should behave similarly on the others.
Apply updates before installing GitLab Runner, configure the correct time zone, and enable NTP. Australian teams may span Sydney, Melbourne, Brisbane, Perth, and Adelaide, so storing timestamps in UTC avoids confusion when daylight-saving changes affect some states but not others. Keep the operating system minimal and remove services that are not required for CI.
A management laptop should reach the nodes over SSH, while the runners need outbound HTTPS access to the GitLab instance, container registries, and package repositories. If remote administration is needed, a WireGuard VPN guide can help establish a private path without exposing SSH directly to the internet.
Install and register the GitLab workers
Install the ARM64 GitLab Runner package using the repository appropriate to the chosen distribution. The runner service should run under its dedicated account, start automatically, and be checked with the system service manager. Verify the binary architecture before registration; an x86 package copied from another machine will not work on a Pi.
Create runners in GitLab with narrowly scoped tags such as arm64, pi, or edge-build. Use authentication tokens supplied by the current GitLab registration process, and avoid placing tokens directly in shell history or committed configuration files. A separate runner per node makes maintenance and troubleshooting much easier than disguising the entire cluster as one opaque worker.
For a small, trusted lab, the shell executor is straightforward and fast. It runs jobs directly on the host, so every pipeline can see installed packages and leftover files. The Docker executor offers better isolation, although Docker images must support ARM64 and nested build requirements can complicate configuration. A useful starting point is one shell runner for scripts and one container-based runner for reproducible application builds.
Shape pipelines for ARM hardware
Build jobs should declare their requirements clearly. Tags can send ARM-specific tasks to the Pi pool, while rules prevent x86-only jobs from being scheduled there. Cache package directories carefully, because repeated downloads can saturate an NBN connection or consume considerable time on slower storage.
Keep individual jobs small and observable. Separate dependency installation, tests, image creation, and publishing so a failure identifies the affected stage. Set timeouts that reflect the Pi’s performance rather than using a desktop-oriented default. For Docker builds, prefer multi-stage Dockerfiles and enable BuildKit where supported.
Useful pipeline design choices include:
- Use ARM64 base images with published digest references.
- Cache Composer, npm, pip, or NuGet dependencies selectively.
- Upload logs and test reports as GitLab artefacts.
- Apply tags that distinguish ARM builds from general-purpose runners.
- Clean workspaces after jobs that handle credentials or large files.
Do not assume every third-party action, binary, or vendor tool has an ARM build. Test the complete pipeline on a single node first, then expand to the rest of the cluster after confirming that package versions and environment variables match.
Secure and maintain the cluster
Treat runners as production infrastructure even when they sit on a desk. A compromised runner can expose repository contents, deployment credentials, and cached artefacts. Use protected runners for protected branches, keep untrusted merge-request jobs away from deployment credentials, and use short-lived tokens wherever the platform supports them.
Restrict SSH with keys, disable password authentication, and place administration on a management VLAN or VPN. The runners should not need inbound internet access. Firewall rules can allow outbound connections to GitLab and approved registries while blocking unnecessary lateral traffic between build nodes.
Maintenance is easier when configuration is documented and repeatable. Store bootstrap scripts in version control, schedule operating-system updates, monitor disk space, and test recovery from a failed SD card or SSD. A small monitoring system can report CPU temperature, load, memory pressure, storage health, and runner availability before developers notice failed jobs.
For infrastructure planning, pricing, and operational comparisons, independent material from SMB Research can add useful context when deciding whether a local cluster or hosted build service fits a small Australian business.
Measure performance and operating cost
Begin with a simple benchmark: record queue time, job duration, cache hit rate, and failure rate for the same pipeline on one Pi and on the existing runner. Then add nodes one at a time. More workers reduce queue time only when the project can run jobs concurrently; they do not make one inherently single-threaded compile faster.
Monitor power supplies and network equipment as part of the total cost. A cluster may draw little power, but four boards, SSDs, cooling fans, and a switch still contribute to a continuous load. Compare that expense with cloud runner pricing, administration time, backup requirements, and the cost of replacing unreliable storage.
A practical operating checklist includes:
- Check runner status and GitLab connectivity after reboots.
- Review disk usage and remove abandoned build directories.
- Test a sample pipeline after OS or Docker upgrades.
- Verify that backups contain runner configuration and scripts.
- Replace failing storage rather than repeatedly repairing it.
This arrangement works particularly well for development teams that need local control, ARM testing, or an inexpensive always-available CI layer. It should complement, rather than replace, a dependable cloud or x86 runner for workloads beyond the Pi cluster’s capacity.
Build the first node as a documented reference, validate a representative GitLab pipeline, and then clone the configuration across the remaining boards. With disciplined tagging, secure credentials, and basic monitoring, a Raspberry Pi cluster can become a dependable part of an Australian development and infrastructure workflow.
Karl Katzke