GitLab Runners Setup
A GitLab Runner is the agent that actually executes your CI/CD pipeline jobs. When GitLab triggers a pipeline, it sends each job to an available runner, which runs the commands and reports the result back.
What a Runner Is — The Delivery Driver Analogy
GitLab (the restaurant) Runner (the delivery driver)
─────────────────────── ─────────────────────────────
Prepares the order Picks up the order
(reads .gitlab-ci.yml) (receives the job)
Sends it out Executes the commands
Returns the result ✅ or ❌
Without a runner, your pipeline jobs queue up and never execute.
Shared Runners vs Specific Runners
| Type | Who Manages It | Available To | Best For |
|---|---|---|---|
| Shared Runner | GitLab.com (free) | All projects on GitLab.com | Quick start, small projects |
| Group Runner | Your team | All projects in one group | Shared team infrastructure |
| Project Runner | Your team | One specific project only | Isolated, sensitive workloads |
GitLab.com Shared Runners — Free Tier
Every account on GitLab.com gets 400 free CI/CD minutes per month on shared runners. These runners run on Linux, Windows, and macOS virtual machines managed by GitLab. No setup required — your pipeline runs as soon as you push a .gitlab-ci.yml file.
Free tier: 400 minutes/month ──────────────────────────────────────────────── Pipeline #1: 12 minutes → 388 remaining Pipeline #2: 8 minutes → 380 remaining Pipeline #3: 15 minutes → 365 remaining ... Pipeline runs until minutes reach 0 for the month
Runner Executors — How Jobs Actually Run
An executor is the method a runner uses to run each job. The most common options are:
| Executor | How It Works | Best For |
|---|---|---|
| Shell | Runs commands directly on the server's shell | Simple setups, single-purpose servers |
| Docker | Spins up a fresh Docker container per job | Isolated, reproducible builds |
| Kubernetes | Creates a Kubernetes pod per job | Large-scale, cloud-native teams |
| VirtualBox | Creates a fresh VM per job | OS-level isolation needs |
The Docker executor is the most popular choice because each job gets a clean, isolated environment defined by the image keyword in your YAML file.
Installing a Self-Hosted Runner on Linux
Use a self-hosted runner when you need more minutes, faster hardware, access to private networks, or special software not available on shared runners.
Step 1 — Download and Install
# Download the runner binary curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash # Install it sudo apt-get install gitlab-runner
Step 2 — Register the Runner
Registration links the runner to your GitLab project or group. Get the registration token from Settings → CI/CD → Runners → New project runner.
sudo gitlab-runner register Prompts you to enter: ───────────────────────────────────────────────── GitLab URL: https://gitlab.com Registration token: glrt-xxxxxxxxxxxx Description: my-linux-runner Tags: linux, docker, production Executor: docker Default image: alpine:latest ───────────────────────────────────────────────── Runner registered successfully ✅
Step 3 — Start the Runner
sudo gitlab-runner start
The runner appears in Settings → CI/CD → Runners as a green dot (online) within a few seconds.
Runner Tags — Routing Jobs to the Right Runner
Tags let you direct specific jobs to specific runners. When you register a runner, you give it tags. In your YAML, a job with matching tags runs only on tagged runners.
Runners available:
─────────────────────────────────────────────
Runner A: tags = [linux, docker]
Runner B: tags = [windows, shell]
Runner C: tags = [macos, xcode]
.gitlab-ci.yml job:
build-ios-app:
stage: build
tags:
- macos
- xcode ← only runs on Runner C
script:
- xcodebuild -scheme MyApp
run-tests:
stage: test
tags:
- linux ← only runs on Runner A
script:
- npm test
Runner Status and Management
View all runners for a project at Settings → CI/CD → Runners. Each runner shows:
- Status (online, offline, or paused)
- Last contact time
- Tags assigned
- Total jobs run
Runners for project: my-webapp ──────────────────────────────────────────────────── 🟢 my-linux-runner online linux, docker 847 jobs 🔴 old-mac-runner offline macos 12 jobs ⏸️ staging-runner paused docker 230 jobs ────────────────────────────────────────────────────
Pausing and Removing a Runner
Pause a runner when you need to take it offline temporarily for maintenance. No new jobs are sent to a paused runner, but running jobs finish. Delete a runner from the three-dot menu next to it in the runners list.
Runner Configuration File
After registration, the runner stores its settings in /etc/gitlab-runner/config.toml. You can edit this file to tune concurrency (how many jobs it runs at once) and other settings.
/etc/gitlab-runner/config.toml
──────────────────────────────────────────
concurrent = 4 ← run up to 4 jobs at the same time
[[runners]]
name = "my-linux-runner"
url = "https://gitlab.com"
executor = "docker"
[runners.docker]
image = "alpine:latest"
privileged = false
Security Best Practices for Runners
- Never run a shared runner with
privileged = true— it gives containers full access to the host machine - Use project-specific runners for jobs that handle secrets or production credentials
- Restrict which projects can use a runner by going to the runner's settings and disabling "Allow projects to add to this runner"
- Keep the runner binary updated — GitLab releases security patches regularly
Checking Runner Logs
If a runner behaves unexpectedly, check its service logs:
sudo gitlab-runner --debug run ← run in foreground with verbose output sudo journalctl -u gitlab-runner ← view system logs on Linux
