Setting Up CI/CD Pipelines with GitLab Runner on Bare Metal

Why Run GitLab Runner on Bare Metal?

Continuous Integration and Continuous Deployment (CI/CD) pipelines are the backbone of modern software delivery. While cloud-hosted runners are convenient, running GitLab Runner on a dedicated server provides predictable performance, lower costs at scale, and full control over your build environment.

With BRHOSTING.COM dedicated servers starting at $158/month, you get AMD EPYC processors with high core counts that excel at parallel CI/CD workloads. A single EPYC 9354P with 32 cores can handle dozens of concurrent build jobs without performance degradation.

Installing GitLab Runner

Add the Official Repository

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

Register the Runner

sudo gitlab-runner register   --url https://gitlab.com/   --registration-token YOUR_TOKEN   --executor docker   --docker-image alpine:latest   --description "bare-metal-runner"   --tag-list "bare-metal,docker,production"

Configuring Docker Executor for Performance

Edit /etc/gitlab-runner/config.toml:

concurrent = 16
check_interval = 3

[[runners]]
  name = "bare-metal-runner"
  executor = "docker"
  [runners.docker]
    image = "alpine:latest"
    privileged = false
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 536870912
    cpus = "4"
    memory = "8g"

Setting concurrent = 16 allows up to 16 parallel jobs. On an EPYC 9354P with 32 cores, allocating 4 CPUs per job leaves headroom for the host system.

Shared Cache with S3-Compatible Storage

[runners.cache]
  Type = "s3"
  Shared = true
  [runners.cache.s3]
    ServerAddress = "minio.internal:9000"
    AccessKey = "runner-cache"
    SecretKey = "your-secret-key"
    BucketName = "gitlab-cache"
    Insecure = false

Optimizing Build Performance

Docker Layer Caching

Enable Docker BuildKit and layer caching in your .gitlab-ci.yml:

variables:
  DOCKER_BUILDKIT: 1
  BUILDKIT_PROGRESS: plain

build:
  stage: build
  script:
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest
      --build-arg BUILDKIT_INLINE_CACHE=1
      -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

Dependency Caching

cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/
    - .npm/

Monitoring Runner Health

GitLab Runner exposes a Prometheus metrics endpoint. Add to your monitoring stack:

listen_address = "0.0.0.0:9252"

Key metrics to watch include gitlab_runner_jobs (active jobs), gitlab_runner_errors_total (failed jobs), and process_resident_memory_bytes (memory usage).

Security Hardening

  • Never enable privileged = true unless absolutely necessary for Docker-in-Docker builds
  • Use separate runners for production deployments with restricted tags
  • Rotate registration tokens regularly
  • Limit network access from build containers using Docker network policies
  • Run GitLab Runner as a non-root service account

Conclusion

Running GitLab Runner on a BRHOSTING.COM dedicated server gives you enterprise-grade CI/CD performance without cloud egress costs. With servers available in Frankfurt, St. Louis, and Singapore, you can place your runners close to your development teams for minimal latency.

Back to Blog