Deploying GitLab Runner
Introduction
GitLab Runner is a powerful open-source continuous integration and deployment agent that works seamlessly with GitLab CI/CD pipelines. It executes jobs defined in .gitlab-ci.yml files, enabling automated testing, building, and deployment workflows for your software projects.
GitLab Runner stands out for its:
- Flexible Executor Support: Run jobs in Docker containers, shells, or virtual machines with multiple executor options
- Scalable Architecture: Deploy multiple runners to handle concurrent jobs and distribute workload efficiently
- Advanced Caching: Built-in cache mechanisms to speed up pipeline executions and reduce build times
- Secure Token Authentication: Token-based registration ensures secure communication with GitLab instances
- Real-Time Log Streaming: Live pipeline execution tracking with detailed logs and status updates
- Tag-Based Job Routing: Use tags to route specific jobs to runners with required capabilities or resources
- Concurrent Job Execution: Configure runners to execute multiple jobs simultaneously based on available resources
- Self-Hosted Control: Complete ownership and control of your CI/CD infrastructure with privacy and compliance benefits
Deploying GitLab Runner on Klutch.sh provides you with a managed, scalable platform for running your CI/CD pipelines with support for Docker-based job execution, persistent storage for caches and artifacts, secure environment variables, and high availability. This comprehensive guide walks you through deploying GitLab Runner using a Dockerfile, including detailed installation steps, runner registration, persistent storage configuration, and production-ready best practices.
Prerequisites
Before you begin, ensure you have the following:
- A Klutch.sh account
- A GitHub account with a repository for your GitLab Runner project
- A GitLab account (GitLab.com or self-hosted GitLab instance)
- Docker installed locally for testing (optional but recommended)
- GitLab Runner registration token from your GitLab project or instance
- Basic understanding of Docker, CI/CD concepts, and GitLab CI/CD pipelines
Installation and Setup
-
Create Your Project Directory
First, create a new directory for your GitLab Runner deployment project:
Terminal window mkdir gitlab-runner-klutchcd gitlab-runner-klutchgit init -
Create the Dockerfile
Create a
Dockerfilein your project root directory. This will define your GitLab Runner container configuration. Klutch.sh automatically detects the Dockerfile in the root directory and uses it for deployment:FROM gitlab/gitlab-runner:latest# Set working directoryWORKDIR /etc/gitlab-runner# Install additional dependencies for Docker-in-Docker supportRUN apt-get update && apt-get install -y \curl \ca-certificates \&& rm -rf /var/lib/apt/lists/*# Create necessary directoriesRUN mkdir -p /etc/gitlab-runner/config \/etc/gitlab-runner/cache \/etc/gitlab-runner/builds# Copy custom configuration if anyCOPY entrypoint.sh /entrypoint.shRUN chmod +x /entrypoint.sh# Expose Prometheus metrics port (optional)EXPOSE 9252# Set default environment variablesENV RUNNER_EXECUTOR=dockerENV DOCKER_IMAGE=alpine:latestENV RUNNER_REQUEST_CONCURRENCY=1# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \CMD gitlab-runner verify --name runner-1 2>&1 | grep -q "is alive" || exit 1# Use custom entrypointENTRYPOINT ["/entrypoint.sh"]Note: This Dockerfile uses the official GitLab Runner image as a base, ensuring compatibility with the latest GitLab CI/CD features. The runner will be configured to use the Docker executor for running jobs in isolated containers.
-
Create Custom Entrypoint Script
Create an
entrypoint.shfile to handle runner registration and startup:#!/bin/bashset -e# Function to register runner if not already registeredregister_runner() {if [ ! -f /etc/gitlab-runner/config/config.toml ]; thenecho "Registering GitLab Runner..."gitlab-runner register \--non-interactive \--url "${GITLAB_URL}" \--registration-token "${REGISTRATION_TOKEN}" \--executor "${RUNNER_EXECUTOR}" \--docker-image "${DOCKER_IMAGE}" \--description "${RUNNER_DESCRIPTION:-gitlab-runner-klutch}" \--tag-list "${RUNNER_TAGS:-docker,klutch}" \--run-untagged="${RUN_UNTAGGED:-false}" \--locked="${RUNNER_LOCKED:-false}" \--access-level="${ACCESS_LEVEL:-not_protected}" \--docker-privileged="${DOCKER_PRIVILEGED:-false}" \--docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \--docker-volumes "/cache" \--config /etc/gitlab-runner/config/config.tomlecho "GitLab Runner registered successfully!"elseecho "Runner already registered, skipping registration..."fi}# Register runner if registration token is providedif [ -n "${REGISTRATION_TOKEN}" ]; thenregister_runnerelseecho "Warning: REGISTRATION_TOKEN not set, skipping automatic registration"echo "You can register manually using: gitlab-runner register"fi# Start GitLab Runnerecho "Starting GitLab Runner..."exec gitlab-runner run \--config /etc/gitlab-runner/config/config.toml \--working-directory /etc/gitlab-runner/builds \--user gitlab-runnerThis script automatically registers the runner on first startup if a registration token is provided, and starts the runner service.
-
Advanced Dockerfile with Docker-in-Docker Support
For running Docker commands within your CI/CD jobs, use this advanced configuration:
FROM gitlab/gitlab-runner:latest# Install Docker CLI and additional toolsRUN apt-get update && apt-get install -y \apt-transport-https \ca-certificates \curl \gnupg \lsb-release \git \jq \&& curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \&& apt-get update \&& apt-get install -y docker-ce-cli \&& rm -rf /var/lib/apt/lists/*# Set working directoryWORKDIR /etc/gitlab-runner# Create necessary directories with proper permissionsRUN mkdir -p /etc/gitlab-runner/config \/etc/gitlab-runner/cache \/etc/gitlab-runner/builds \/etc/gitlab-runner/certs \&& chown -R gitlab-runner:gitlab-runner /etc/gitlab-runner# Copy entrypoint scriptCOPY entrypoint.sh /entrypoint.shRUN chmod +x /entrypoint.sh# Expose Prometheus metrics portEXPOSE 9252# Environment variablesENV RUNNER_EXECUTOR=dockerENV DOCKER_IMAGE=alpine:latestENV RUNNER_REQUEST_CONCURRENCY=1ENV CI_SERVER_URL=""ENV REGISTRATION_TOKEN=""ENV RUNNER_NAME=gitlab-runner-klutchENV RUNNER_TAGS=docker,klutch# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \CMD gitlab-runner verify 2>&1 | grep -q "is alive" || exit 1# Use custom entrypointENTRYPOINT ["/entrypoint.sh"] -
Create Configuration Template
Create a
config.toml.templatefile for advanced runner configurations:concurrent = ${CONCURRENT_JOBS:-4}check_interval = 0log_level = "${LOG_LEVEL:-info}"[session_server]session_timeout = 1800[[runners]]name = "${RUNNER_NAME:-gitlab-runner-klutch}"url = "${GITLAB_URL}"token = "${RUNNER_TOKEN}"executor = "docker"limit = ${RUNNER_LIMIT:-0}request_concurrency = ${RUNNER_REQUEST_CONCURRENCY:-1}[runners.custom_build_dir]enabled = true[runners.cache]Type = "local"Path = "/etc/gitlab-runner/cache"Shared = true[runners.cache.local]MaxUploadedArchiveSize = 0[runners.docker]tls_verify = falseimage = "${DOCKER_IMAGE:-alpine:latest}"privileged = ${DOCKER_PRIVILEGED:-false}disable_entrypoint_overwrite = falseoom_kill_disable = falsedisable_cache = falsevolumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]shm_size = 0pull_policy = ["if-not-present"] -
Create .gitignore File
Create a
.gitignorefile to exclude sensitive and build files:# Runner configuration (contains tokens)config.toml# Cache and build directoriescache/builds/# Environment variables.env.env.local# Logs*.log# IDE.vscode/.idea/ -
Create README.md
Create a
README.mdfile with basic instructions:# GitLab Runner on Klutch.shThis repository contains the configuration for deploying GitLab Runner on Klutch.sh.## Quick Start1. Set up environment variables in Klutch.sh dashboard2. Deploy the application3. Runner will automatically register and start processing jobs## Required Environment Variables- `GITLAB_URL`: Your GitLab instance URL (e.g., https://gitlab.com)- `REGISTRATION_TOKEN`: Runner registration token from GitLabSee the full documentation for more details. -
Initialize Git and Push to GitHub
Initialize your repository and push it to GitHub:
Terminal window git add .git commit -m "Initial GitLab Runner setup for Klutch.sh"git branch -M maingit remote add origin https://github.com/yourusername/gitlab-runner-klutch.gitgit push -u origin main
Deploying on Klutch.sh
-
Connect Your GitHub Repository
- Navigate to klutch.sh/app
- Click “New Project” or select an existing project
- Click “New App” and select “Import from GitHub”
- Authorize Klutch.sh to access your GitHub account if you haven’t already
- Select your GitLab Runner repository from the list
-
Configure Build Settings
Since Klutch.sh automatically detects the Dockerfile in your repository root, the build configuration is handled automatically. The platform uses Nixpacks as the build system, but when a Dockerfile is present, it takes precedence.
-
Configure the Internal Port
GitLab Runner primarily communicates outbound to GitLab, but if you want to expose Prometheus metrics:
- In the app configuration, set the Internal Port to
9252(for metrics endpoint) - Select HTTP as the traffic type
- This is optional; the runner will work without exposing this port
- In the app configuration, set the Internal Port to
-
Set Up Persistent Storage
GitLab Runner requires persistent storage for configuration, cache, and build artifacts:
In your app settings, add the following volume mounts:
- Mount Path:
/etc/gitlab-runner/config| Size: 1 GB (for runner configuration) - Mount Path:
/etc/gitlab-runner/cache| Size: 20 GB (for job caches) - Mount Path:
/etc/gitlab-runner/builds| Size: 10 GB (for job workspaces)
Note: Adjust the cache and builds volume sizes based on your pipeline requirements. Projects with large artifacts or many concurrent jobs may require more storage.
- Mount Path:
-
Obtain GitLab Runner Registration Token
Before configuring environment variables, you need to obtain a runner registration token from GitLab:
For Project-Specific Runner:
- Navigate to your GitLab project
- Go to Settings → CI/CD
- Expand the Runners section
- Find the Project runners section
- Click “New project runner”
- Configure runner settings and tags
- Copy the registration token displayed
For Group Runner:
- Navigate to your GitLab group
- Go to Settings → CI/CD
- Expand the Runners section
- Click “New group runner”
- Configure runner settings and tags
- Copy the registration token displayed
For Instance Runner (Self-Hosted GitLab):
- Navigate to Admin Area → CI/CD → Runners
- Click “New instance runner”
- Configure runner settings
- Copy the registration token displayed
-
Configure Environment Variables
Add the following environment variables in your Klutch.sh app settings. Mark sensitive values as secret:
Required Configuration:
GITLAB_URL=https://gitlab.comREGISTRATION_TOKEN=<mark-as-secret>Runner Configuration:
RUNNER_DESCRIPTION=gitlab-runner-klutchRUNNER_TAGS=docker,klutch,linuxRUNNER_EXECUTOR=dockerDOCKER_IMAGE=alpine:latestRUN_UNTAGGED=falseRUNNER_LOCKED=falseACCESS_LEVEL=not_protectedConcurrency Settings:
CONCURRENT_JOBS=4RUNNER_REQUEST_CONCURRENCY=1RUNNER_LIMIT=0Docker Executor Settings:
DOCKER_PRIVILEGED=falseDOCKER_PULL_POLICY=if-not-presentOptional - Advanced Settings:
LOG_LEVEL=infoMETRICS_SERVER=:9252SENTRY_DSN=<mark-as-secret>Note: If you’re using self-hosted GitLab, replace
https://gitlab.comwith your GitLab instance URL. TheREGISTRATION_TOKENis sensitive and should always be marked as secret. -
Deploy the Application
- Review all configurations
- Click “Deploy” to start the deployment
- Klutch.sh will build the Docker image from your Dockerfile and deploy it
- Monitor the build logs to ensure everything completes successfully
-
Verify the Deployment
Once the deployment is complete:
- Check the application logs in Klutch.sh dashboard for successful registration message
- Navigate to your GitLab project’s Settings → CI/CD → Runners
- Verify that your runner appears in the list with a green status indicator
- The runner should show as “online” and ready to accept jobs
- Trigger a test pipeline to verify the runner picks up and executes jobs
Runner Registration Process
GitLab Runner must be registered with your GitLab instance before it can execute jobs. The registration process associates the runner with your GitLab project, group, or instance.
Automatic Registration
The provided entrypoint.sh script automatically registers the runner on first startup when the following environment variables are set:
GITLAB_URL: Your GitLab instance URLREGISTRATION_TOKEN: The registration token from GitLab
The registration includes:
- Runner Description: Human-readable name for the runner
- Tags: Labels for routing specific jobs to this runner
- Executor Type: How jobs are executed (Docker, shell, etc.)
- Docker Configuration: Default Docker image and settings
- Concurrent Jobs: Number of jobs that can run simultaneously
Manual Registration
If you need to register the runner manually or update registration settings:
-
Access the container shell through Klutch.sh dashboard
-
Run the registration command:
Terminal window gitlab-runner register \--non-interactive \--url "https://gitlab.com" \--registration-token "YOUR_TOKEN" \--executor "docker" \--docker-image "alpine:latest" \--description "gitlab-runner-klutch" \--tag-list "docker,klutch" \--run-untagged="false" \--locked="false" -
The runner configuration will be saved to
/etc/gitlab-runner/config/config.toml
Verifying Runner Registration
Check runner status:
gitlab-runner verifyList registered runners:
gitlab-runner listConfiguring GitLab CI/CD Pipelines
To use your deployed GitLab Runner, you need to configure your .gitlab-ci.yml file to use the runner’s tags.
Basic Pipeline Example
Create a .gitlab-ci.yml file in your GitLab project:
# Define stagesstages: - build - test - deploy
# Build stagebuild-job: stage: build tags: - docker - klutch script: - echo "Building the application..." - npm install - npm run build artifacts: paths: - dist/ expire_in: 1 hour
# Test stagetest-job: stage: test tags: - docker - klutch script: - echo "Running tests..." - npm test dependencies: - build-job
# Deploy stagedeploy-job: stage: deploy tags: - docker - klutch script: - echo "Deploying application..." - ./deploy.sh only: - main dependencies: - build-jobAdvanced Pipeline with Docker
For pipelines that need to build Docker images:
stages: - build - test - publish
variables: DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: ""
build-docker-image: stage: build tags: - docker - klutch image: docker:latest services: - docker:dind before_script: - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
run-tests: stage: test tags: - docker - klutch image: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA script: - npm test - npm run test:integration
publish-release: stage: publish tags: - docker - klutch image: docker:latest services: - docker:dind script: - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest - docker push $CI_REGISTRY_IMAGE:latest only: - mainUsing Caching
Leverage GitLab Runner’s cache to speed up builds:
cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ - .npm/
build: tags: - docker - klutch script: - npm ci --cache .npm --prefer-offline - npm run build cache: key: ${CI_COMMIT_REF_SLUG} paths: - node_modules/ - .npm/ policy: pull-pushEnvironment Variables Reference
Required Environment Variables
| Variable | Description | Example |
|---|---|---|
GITLAB_URL | GitLab instance URL | https://gitlab.com |
REGISTRATION_TOKEN | Runner registration token from GitLab | GR1348941... |
Runner Configuration Variables
| Variable | Description | Default |
|---|---|---|
RUNNER_DESCRIPTION | Human-readable runner name | gitlab-runner-klutch |
RUNNER_TAGS | Comma-separated list of tags | docker,klutch |
RUNNER_EXECUTOR | Executor type (docker, shell, etc.) | docker |
DOCKER_IMAGE | Default Docker image for jobs | alpine:latest |
RUN_UNTAGGED | Run jobs without tags | false |
RUNNER_LOCKED | Lock runner to current project | false |
ACCESS_LEVEL | Runner access level | not_protected |
Concurrency and Performance
| Variable | Description | Default |
|---|---|---|
CONCURRENT_JOBS | Maximum concurrent jobs | 4 |
RUNNER_REQUEST_CONCURRENCY | Concurrent job requests | 1 |
RUNNER_LIMIT | Maximum jobs to run (0 = unlimited) | 0 |
Docker Executor Settings
| Variable | Description | Default |
|---|---|---|
DOCKER_PRIVILEGED | Enable privileged mode | false |
DOCKER_PULL_POLICY | When to pull Docker images | if-not-present |
DOCKER_VOLUMES | Additional volumes to mount | /var/run/docker.sock:/var/run/docker.sock |
Optional Settings
| Variable | Description | Default |
|---|---|---|
LOG_LEVEL | Logging level (debug, info, warn, error) | info |
METRICS_SERVER | Prometheus metrics endpoint | :9252 |
SENTRY_DSN | Sentry error tracking DSN | (empty) |
Nixpacks Environment Variables
Since Klutch.sh automatically detects and uses the Dockerfile, these Nixpacks variables are only relevant if you’re deploying without a Dockerfile:
| Variable | Description | Example |
|---|---|---|
NIXPACKS_BUILD_CMD | Custom build command | echo "Build complete" |
NIXPACKS_START_CMD | Custom start command | /entrypoint.sh |
Note: When a Dockerfile is present, Nixpacks variables are not used as Docker takes precedence.
Persistent Storage Best Practices
Storage Layout
Organize your persistent storage for optimal performance and management:
/etc/gitlab-runner/├── config/│ └── config.toml # Runner configuration (contains tokens)├── cache/ # Job caches for faster builds│ ├── runner-1/│ └── runner-2/├── builds/ # Job workspaces│ ├── project-1/│ └── project-2/└── certs/ # TLS certificates (if needed)Volume Size Recommendations
Based on project scale and pipeline complexity:
Small Projects (1-5 pipelines/day):
- Config: 1 GB
- Cache: 5 GB
- Builds: 5 GB
Medium Projects (5-20 pipelines/day):
- Config: 1 GB
- Cache: 20 GB
- Builds: 10 GB
Large Projects (20+ pipelines/day):
- Config: 2 GB
- Cache: 50 GB+
- Builds: 20 GB
Cache Management
Configure cache cleanup to manage storage:
[[runners]] [runners.cache] Type = "local" Path = "/etc/gitlab-runner/cache" Shared = true MaxUploadedArchiveSize = 1073741824 # 1GB
[runners.cache.local] MaxUploadedArchiveSize = 0Implement periodic cache cleanup:
# Cleanup script#!/bin/bashCACHE_DIR=/etc/gitlab-runner/cacheRETENTION_DAYS=7
# Remove caches older than retention periodfind $CACHE_DIR -type f -mtime +$RETENTION_DAYS -deletefind $CACHE_DIR -type d -empty -deleteProduction Best Practices
Security
-
Secure Registration Tokens: Always mark
REGISTRATION_TOKENas secret in Klutch.sh -
Principle of Least Privilege: Use project-specific runners instead of instance-wide runners when possible
-
Disable Privileged Mode: Only enable
DOCKER_PRIVILEGED=trueif absolutely necessary for your pipelines -
Regular Updates: Keep GitLab Runner updated to the latest version
FROM gitlab/gitlab-runner:latest -
Rotate Tokens: Periodically rotate runner registration tokens
-
Network Security: Use private networks for communication between runners and GitLab
High Availability
-
Multiple Runners: Deploy multiple runner instances for redundancy
-
Health Monitoring: Use the built-in health check endpoint
Terminal window curl http://example-app.klutch.sh:9252/metrics -
Automatic Restart: Klutch.sh automatically restarts failed containers
-
Load Distribution: Use runner tags to distribute jobs across multiple runners
Performance Optimization
-
Concurrent Jobs: Configure based on available resources
CONCURRENT_JOBS=4 -
Cache Dependencies: Use GitLab CI/CD cache to speed up builds
-
Docker Image Caching: Set pull policy to
if-not-presentto avoid unnecessary pulls -
Resource Limits: Configure appropriate CPU and memory limits in Klutch.sh
-
Local Docker Registry: Consider using a registry cache to speed up image pulls
Monitoring and Alerts
Monitor the following metrics:
- Runner availability and uptime
- Job queue length and wait times
- Job success/failure rates
- Cache hit rates
- Storage usage trends
- Container resource utilization
Access Prometheus metrics:
curl http://example-app.klutch.sh:9252/metricsKey metrics to track:
gitlab_runner_jobs: Current jobs runninggitlab_runner_job_duration_seconds: Job execution timesgitlab_runner_errors_total: Error countsgitlab_runner_concurrent_requests: Concurrent job requests
Troubleshooting
Common Issues
Issue: Runner fails to register
- Solution: Verify
GITLAB_URLandREGISTRATION_TOKENare correct - Debug: Check application logs for registration errors
- Verify: Ensure network connectivity to GitLab instance
Issue: Jobs not being picked up by runner
- Solution: Check that job tags in
.gitlab-ci.ymlmatch runner tags - Debug: Verify runner is online in GitLab UI
- Check: Ensure
RUN_UNTAGGEDis set totrueif jobs have no tags
Issue: Docker-in-Docker not working
- Solution: Verify Docker socket is mounted correctly in volumes
- Alternative: Enable privileged mode with
DOCKER_PRIVILEGED=true - Check: Ensure Docker service is available in job containers
Issue: Out of storage space
- Solution: Implement cache cleanup or increase volume sizes
- Debug: Check storage usage:
df -h /etc/gitlab-runner - Clean: Manually remove old caches and builds
Issue: Jobs timeout or hang
- Solution: Increase job timeout in
.gitlab-ci.yml - Check: Review job logs for specific errors
- Verify: Ensure sufficient resources (CPU/memory) are allocated
Issue: TLS certificate verification failed
- Solution: Add custom certificates to
/etc/gitlab-runner/certs/ - Alternative: Set
tls_verify = falsein config.toml (not recommended for production) - Debug: Check GitLab instance SSL certificate validity
Debug Mode
Enable debug logging for troubleshooting:
LOG_LEVEL=debugVerifying Runner Status
Check runner status from container:
# List registered runnersgitlab-runner list
# Verify runner connectivitygitlab-runner verify
# Check runner statusgitlab-runner statusAccessing Runner Configuration
View runner configuration:
cat /etc/gitlab-runner/config/config.tomlTesting Runner Manually
Trigger a test job:
test-runner: tags: - docker - klutch script: - echo "Testing GitLab Runner on Klutch.sh" - gitlab-runner --version - docker --versionAdvanced Configuration
Custom Docker Images
Configure runner to use custom Docker images with pre-installed dependencies:
[[runners]] [runners.docker] image = "your-registry.com/custom-image:latest" pull_policy = ["if-not-present"]Docker Socket Binding
For jobs that need Docker access:
[[runners]] [runners.docker] volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]Security Note: Mounting Docker socket gives jobs full Docker daemon access. Use with caution.
Resource Limits
Configure resource limits for job containers:
[[runners]] [runners.docker] memory = "2g" memory_swap = "2g" memory_reservation = "1g" cpus = "2"Network Configuration
Configure custom networks for job isolation:
[[runners]] [runners.docker] network_mode = "bridge" dns = ["8.8.8.8", "8.8.4.4"]Service Containers
Enable service containers for integration tests:
integration-test: tags: - docker - klutch services: - postgres:13 - redis:6 variables: POSTGRES_DB: testdb POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass script: - npm run test:integrationCustom Executor Scripts
For advanced use cases, create custom executor scripts:
[[runners]] name = "custom-shell-runner" executor = "shell" shell = "bash" builds_dir = "/etc/gitlab-runner/builds" cache_dir = "/etc/gitlab-runner/cache"Scaling GitLab Runners
Horizontal Scaling
Deploy multiple runner instances for increased capacity:
- Create Multiple Apps: Deploy separate GitLab Runner apps on Klutch.sh
- Use Shared Tags: Configure all runners with the same tags for load distribution
- Dedicated Runners: Assign specific runners to specific projects or job types
Autoscaling Considerations
While Klutch.sh doesn’t directly support runner autoscaling, you can:
- Deploy Multiple Static Runners: Create several runner instances for peak capacity
- Use Runner Limits: Configure
RUNNER_LIMITto control maximum jobs per runner - Tag-Based Routing: Route resource-intensive jobs to dedicated runners
Runner Fleet Management
Manage multiple runners effectively:
# Runner naming conventiongitlab-runner-klutch-1 # General purposegitlab-runner-klutch-2 # General purposegitlab-runner-klutch-docker # Docker buildsgitlab-runner-klutch-deploy # Deployments onlyConfigure different concurrency levels:
- General purpose:
CONCURRENT_JOBS=4 - Docker builds:
CONCURRENT_JOBS=2(resource intensive) - Deployments:
CONCURRENT_JOBS=1(serial execution)
Docker Compose for Local Development
For local testing before deploying to Klutch.sh, use this Docker Compose configuration:
version: '3.8'
services: gitlab-runner: build: . environment: - GITLAB_URL=https://gitlab.com - REGISTRATION_TOKEN=your-token-here - RUNNER_DESCRIPTION=gitlab-runner-local - RUNNER_TAGS=docker,local - RUNNER_EXECUTOR=docker - DOCKER_IMAGE=alpine:latest - CONCURRENT_JOBS=2 - LOG_LEVEL=debug volumes: - ./config:/etc/gitlab-runner/config - ./cache:/etc/gitlab-runner/cache - ./builds:/etc/gitlab-runner/builds - /var/run/docker.sock:/var/run/docker.sock privileged: false restart: unless-stopped
volumes: runner-config: runner-cache: runner-builds:Run locally with:
docker-compose up -dNote: Docker Compose is only for local development. Klutch.sh does not support Docker Compose for deployments.
Migration from Other Platforms
From Jenkins
If you’re migrating from Jenkins:
- Convert Jenkinsfile stages to GitLab CI stages
- Replace Jenkins agents with GitLab Runner tags
- Migrate Jenkins credentials to GitLab CI/CD variables
- Update deployment scripts to use GitLab CI/CD syntax
From CircleCI
Converting CircleCI workflows:
- Map CircleCI orbs to GitLab CI templates or custom scripts
- Convert
.circleci/config.ymlto.gitlab-ci.yml - Replace CircleCI contexts with GitLab groups and variables
- Update artifact storage and caching configurations
From Travis CI
Migrating from Travis CI:
- Convert
.travis.ymlto.gitlab-ci.ymlformat - Replace Travis CI environment variables with GitLab CI/CD variables
- Update deployment provider configurations
- Migrate encrypted secrets to GitLab protected variables
Security Best Practices
Token Management
- Never Commit Tokens: Keep registration tokens out of version control
- Use Protected Variables: Mark sensitive variables as protected in GitLab
- Rotate Regularly: Change registration tokens periodically
- Scope Appropriately: Use project runners instead of shared runners for sensitive projects
Job Security
- Validate Input: Always validate external input in job scripts
- Use Protected Branches: Require protected branches for deployment jobs
- Limit Runner Access: Use tags to control which jobs run on which runners
- Audit Pipeline Logs: Regularly review pipeline logs for suspicious activity
Network Security
- Private Networking: Use private networks between runners and services
- Firewall Rules: Restrict runner network access to required services only
- TLS Everywhere: Use HTTPS for all GitLab communications
- VPN/Bastion: Consider VPN or bastion hosts for production runners
Container Security
- Non-Root User: Run jobs as non-root user when possible
- Read-Only Filesystems: Use read-only root filesystem where applicable
- Security Scanning: Integrate container security scanning in pipelines
- Minimal Images: Use minimal base images (Alpine, distroless)
Backup and Monitoring
Configuration Backup
Regularly backup runner configuration:
# Backup script#!/bin/bashBACKUP_DIR=/backupsDATE=$(date +%Y%m%d_%H%M%S)CONFIG_FILE=/etc/gitlab-runner/config/config.toml
# Create backupcp $CONFIG_FILE "${BACKUP_DIR}/config.toml.${DATE}"
# Keep only last 7 backupsls -t ${BACKUP_DIR}/config.toml.* | tail -n +8 | xargs rm -fCache and Build Backup
Backup important caches and artifacts:
# Backup cachestar -czf cache_backup_$(date +%Y%m%d).tar.gz /etc/gitlab-runner/cache
# Backup critical buildstar -czf builds_backup_$(date +%Y%m%d).tar.gz /etc/gitlab-runner/buildsMonitoring Setup
Monitor runner health:
- Metrics Endpoint: Expose port 9252 for Prometheus metrics
- Log Aggregation: Send logs to external logging service
- Alerting: Set up alerts for runner downtime or job failures
- Dashboard: Create Grafana dashboard for runner metrics
Health Checks
Implement comprehensive health checks:
#!/bin/bash# Check runner serviceif ! gitlab-runner verify &>/dev/null; then echo "Runner verification failed" exit 1fi
# Check storageCACHE_USAGE=$(df -h /etc/gitlab-runner/cache | awk 'NR==2 {print $5}' | sed 's/%//')if [ $CACHE_USAGE -gt 90 ]; then echo "Cache storage critical: ${CACHE_USAGE}%" exit 1fi
echo "Health check passed"exit 0