GitLab Runner Offline: Fix in 5 Minutes
GitLab Runner showing as offline or stale even though the process is running? Here is exactly how to diagnose token issues, network connectivity, version mismatches, and concurrency exhaustion behind a stuck runner.
A runner marked offline in GitLab's UI while the process on the machine looks fine is one of the more confusing states — the runner and GitLab disagree about connectivity, and the error rarely points at the real cause directly.
Step 1: Confirm the Runner Process Is Actually Healthy
sudo gitlab-runner status
# gitlab-runner: pid, beat: 500ms
sudo gitlab-runner verify
# Verifying runner... is alive runner=AbCdEfGhIf verify succeeds but GitLab's UI still shows offline, the issue is in the heartbeat/registration path, not the runner process itself.
Cause 1: Runner Token Was Reset or Revoked
sudo cat /etc/gitlab-runner/config.toml
# [[runners]]
# token = "glrt-xxxxxxxxxxxx"If someone regenerated the project/group runner registration token in GitLab (common during a security rotation), existing runners using the old token silently stop authenticating — no clear error, they just go offline.
# Check the runner logs for auth failures
sudo journalctl -u gitlab-runner -n 100 --no-pager | grep -i "40[13]\|unauthorized\|forbidden"Fix — re-register with the current token:
sudo gitlab-runner unregister --name my-runner
sudo gitlab-runner register \
--url https://gitlab.com/ \
--registration-token NEW_TOKEN \
--executor docker \
--docker-image alpine:latestCause 2: Runner Can't Reach GitLab (Network/Firewall)
# Test actual connectivity from the runner host
curl -v https://gitlab.com/api/v4/versionIf this hangs or fails, the runner's heartbeat requests are failing silently — GitLab marks a runner offline after it misses heartbeats for a few minutes, with no error surfaced on the runner side beyond connection timeouts in the logs.
sudo journalctl -u gitlab-runner -n 100 --no-pager | grep -i "timeout\|connection refused\|no route"Fix — check firewall/proxy rules for outbound HTTPS to your GitLab instance:
# If behind a corporate proxy, the runner needs it configured explicitly —
# it does not inherit shell environment proxy settings automatically
sudo systemctl edit gitlab-runner[Service]
Environment="HTTPS_PROXY=http://proxy.internal:8080"
Environment="NO_PROXY=localhost,127.0.0.1"sudo systemctl daemon-reload
sudo systemctl restart gitlab-runnerCause 3: Clock Skew Between Runner Host and GitLab
timedatectl status
# If "System clock synchronized: no" — this can cause heartbeat/token
# validation to fail intermittentlyFix — ensure NTP sync is active:
sudo timedatectl set-ntp true
sudo systemctl restart systemd-timesyncdClock skew of more than a few minutes can cause token/JWT-based auth to fail in ways that look exactly like a connectivity problem.
Cause 4: Runner Version Too Old for the GitLab Server Version
gitlab-runner --version
# Compare against your GitLab instance's version — GitLab officially
# supports runners within 2 minor versions, older ones can behave unpredictablyFix — update the runner:
# Debian/Ubuntu
sudo apt-get update && sudo apt-get install gitlab-runner
# Or via the official install script for a specific version
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runnerCause 5: concurrent Limit Exhausted, New Jobs Queue and Runner Appears Stuck
# /etc/gitlab-runner/config.toml
concurrent = 4 # Only 4 jobs can run simultaneously across all configured runnersIf all concurrent slots are occupied by long-running or hung jobs, new jobs queue indefinitely and the runner can appear unresponsive even though it's technically online.
sudo gitlab-runner list # Shows configured runners and their concurrencyFix — increase concurrency if the host has capacity, and investigate why jobs are running long:
concurrent = 8sudo systemctl restart gitlab-runnerDiagnostic Checklist
sudo gitlab-runner status # process health
sudo gitlab-runner verify # token validity against GitLab
curl -v https://gitlab.com/api/v4/version # network path
timedatectl status # clock sync
gitlab-runner --version # version skew check
sudo journalctl -u gitlab-runner -n 100 --no-pager # actual error detailMore CI/CD troubleshooting? Read our GitLab CI pipeline failing fix and GitHub Actions workflow not triggering fix.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
AWS CodeBuild Build Failing or Timing Out — Fix Guide
CodeBuild exits with status 1, times out mid-build, or fails with cryptic phase errors. Here's how to diagnose DOWNLOAD_SOURCE, BUILD, and POST_BUILD failures with specific fixes.
AWS ECR Push Denied: no basic auth credentials — Fix
Getting 'no basic auth credentials' or 'denied: Your authorization token has expired' when pushing to AWS ECR? Here are the exact commands to fix authentication for Docker, GitHub Actions, and Kubernetes.
AWS ECS Service Still Running Old Task Definition After Update
ECS service ignoring your new task definition revision? Fix it with force-new-deployment, understand pinned ARNs vs LATEST, check the deployment circuit breaker, and verify which revision is actually running.