How to Set Up GitLab CI/CD Runners on a VPS

If you use GitLab for source control, self-hosting your own CI/CD runners gives you full control over the build environment and avoids shared-runner queue times. This guide covers setting up a GitLab Runner on a VPS.

Why Self-Host Runners

GitLab.com's shared runners work well for many projects, but a self-hosted runner gives you dedicated capacity, custom environment control, and can be more cost-effective for consistent, heavy build workloads — similar rationale to How to Set Up a Self-Hosted GitHub Actions Runner on a VPS.

Step 1 — Install GitLab Runner

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install gitlab-runner -y

Step 2 — Get a Registration Token from GitLab

In your GitLab project or group: Settings > CI/CD > Runners — copy the registration token needed for the next step.

Step 3 — Register the Runner

sudo gitlab-runner register

Follow the interactive prompts: GitLab instance URL, registration token, description, and executor type.

Choosing an Executor Type

ExecutorUse Case
shellSimple, runs directly on the VPS — least isolation
dockerEach job runs in an isolated container — recommended for most cases

Step 4 — Configure the Docker Executor (Recommended)

Executor = "docker"
[runners.docker]
  image = "ubuntu:22.04"

The Docker executor provides genuine job isolation — each pipeline run gets a clean container, avoiding state leaking between builds, similar in spirit to How to Set Up Zero-Downtime Deployments with Docker's isolation approach.

Step 5 — Verify the Runner Is Active

Check Settings > CI/CD > Runners in GitLab — your new runner should appear as active/online.

Creating a .gitlab-ci.yml Pipeline

stages:
  - test
  - deploy

test:
  stage: test
  script:
    - npm install
    - npm test

deploy:
  stage: deploy
  script:
    - ./deploy.sh
  only:
    - main

Restricting the Runner to Specific Projects

By default, a project-registered runner only serves that specific project — if registering a group-level or shared runner, be deliberate about scope, since a broader-scope runner processes jobs from more sources, increasing the security surface if a job is malicious/compromised.

Security: Isolating Runner Jobs

See CI/CD Pipeline Security Best Practices — the same core principles apply regardless of CI platform: don't run untrusted code with excessive privileges, and isolate build environments from your production infrastructure's credentials.

Scaling Runners for Concurrent Jobs

concurrent = 4

Adjust the concurrent job limit in /etc/gitlab-runner/config.toml based on your VPS's actual capacity — too high a concurrency setting on limited hardware causes resource contention degrading all concurrent builds.

Common Errors

Runner shows as offline despite the service running — verify network connectivity to your GitLab instance, and check gitlab-runner logs (journalctl -u gitlab-runner) for connection or authentication errors.

Continue Reading

Browse more articles in DevOps & CI/CD.

  • gitlab runner setup, self hosted gitlab ci, gitlab-ci.yml example, gitlab docker executor
  • 0 Users Found This Useful
Was this answer helpful?

Related Articles

How to Set Up a Self-Hosted GitHub Actions Runner on a VPS

GitHub Actions' hosted runners work well for most projects, but a self-hosted runner on your own...

How to Deploy Automatically on Git Push (Webhook-Based Deployment)

Automating deployment whenever you push to a specific branch removes the manual "SSH in and pull"...

How to Set Up Blue-Green Deployment on a VPS

Blue-green deployment runs two identical production environments — only one live at a time...

How to Use Ansible for Server Configuration Management

Ansible automates server configuration through simple, human-readable YAML files — letting...

Infrastructure as Code Basics: Managing VPS Config with Terraform

Terraform lets you define infrastructure (VPS instances, networks, DNS records) as code, applied...