E-NO
GitLab CI/CD commands 7 Min Read

GitLab CI/CD Basic Commands with Practical Examples: A Day-to-Day Operator's Guide

calendar_today Published: 2026-10-25
update Last Updated: 2026-10-25
analytics SEO Efficiency: 100%
Technical guide illustration for GitLab CI/CD Basic Commands with Practical Examples: A Day-to-Day Operator's Guide.

Intro

GitLab CI/CD basic commands with practical examples should move you from an observed problem to a verified fix. Start by identifying the installed version, deployment topology, prerequisites, and the exact component you are inspecting.

This guide is for developers, DevOps consultants, and technical startup teams who operate GitLab CI/CD daily. It connects basic commands, practical examples, and a cheat-sheet approach to operational safety: observe before changing, limit blast radius, use placeholders instead of secrets, verify every result, and document recovery paths.

Every procedure below follows the same pattern:

  1. Read-only observation first.
  2. Define expected result and failure signal before changing anything.
  3. Make the smallest justified change with a known rollback.
  4. Verify the outcome with a concrete command or API response.

No real credentials, tokens, private keys, or production identifiers appear in this article. Replace all placeholders with your own values.

Version and Environment Inventory

Before running any GitLab CI/CD command, know what you are working with. The version determines which flags, API endpoints, and configuration syntax are valid. The topology tells you where runners live, how they connect, and what logs you can reach.

1. Check GitLab server version

Use the version API or the Rails console on the GitLab instance.

# From the GitLab host (read-only)
sudo gitlab-rake gitlab:env:info

Expected output includes:

GitLab information
Version:        16.11.0
Revision:       1234567
Directory:      /opt/gitlab/embedded/service/gitlab-rails
DB Adapter:     PostgreSQL
URL:            https://gitlab.example.com
HTTP Clone URL: https://gitlab.example.com/some-group/some-project.git
SSH Clone URL:  [email protected]:some-group/some-project.git

Failure signals:

  • "Permission denied" -> you need sudo or GitLab admin access.
  • "rake aborted" -> GitLab installation may be broken; check gitlab-ctl status.

2. Check GitLab Runner version

On each runner host:

gitlab-runner --version

Expected output:

Version:      16.11.0
Git revision: 4b5e6f1
Git branch:   16-11-stable
GO version:   go1.21.5
Built:        2024-01-15T14:00:00Z
OS/Arch:      linux/amd64

Why versions matter: Runner 16.x uses --registration-token for runner registration; newer versions may use an authentication token from the UI. Mixing versions can lead to "500 Internal Server Error" during job registration.

3. List registered runners (requires admin token)

The runners API shows all runners, their status, tags, and executors. Use a read-only GET request with an admin personal access token (PAT).

curl --header "PRIVATE-TOKEN: <your_admin_pat>" \
  "https://gitlab.example.com/api/v4/runners?per_page=50"

A healthy runner response includes:

[
  {
    "id": 42,
    "description": "docker-runner-prod",
    "active": true,
    "online": true,
    "status": "online",
    "runner_type": "group_type",
    "tag_list": ["docker", "linux", "prod"]
  }
]

Failure signals:

  • HTTP 401 -> invalid PAT or missing read_api scope.
  • Empty array [] -> no runners registered or token lacks permission.

4. Record current state before any change

Write down the output of the commands above, including timestamps. This is your rollback point. For example:

date -u +"%Y-%m-%dT%H:%M:%SZ"
sudo gitlab-rake gitlab:env:info > gitlab_env_$(date +%F_%T).log
gitlab-runner --version > runner_version_$(date +%F_%T).log

Store these logs in a secure location, not in the repository.

Safe Configuration Path

Configuration changes should be small, version-appropriate, and reversible. Never edit multiple files at once, and never put secrets in gitlab-ci.yml.

1. Edit gitlab-ci.yml safely

The pipeline definition is the most frequently changed file. Use the GitLab CI Lint API to validate it before pushing.

# Use a project access token or PAT with 'api' scope
curl --header "Content-Type: application/json" \
     --header "PRIVATE-TOKEN: <your_pat>" \
     --data '{"content": "include:\n  - local: /templates/.gitlab-ci-template.yml\n\nstages:\n  - test\n\ntest_job:\n  stage: test\n  script: echo \"Running tests\""}' \
     "https://gitlab.example.com/api/v4/ci/lint"

Expected success response:

{
  "valid": true,
  "errors": [],
  "warnings": [],
  "merged_yaml": "---\ninclude:\n- local: /templates/.gitlab-ci-template.yml\nstages:\n- test\ntest_job:\n  stage: test\n  script: echo 'Running tests'\n"
}

Failure signals:

  • "valid": false with an errors array -> fix syntax before committing.
  • HTTP 401 -> token lacks api scope.

2. Configure a runner for a project

If a project needs a dedicated runner, register it with a project-specific token (obtained from Settings > CI/CD > Runners). Use non-interactive registration to avoid prompts:

sudo gitlab-runner register \
  --non-interactive \
  --url "https://gitlab.example.com" \
  --registration-token "<project_registration_token>" \
  --executor "docker" \
  --docker-image "alpine:3.19" \
  --description "project-x-runner" \
  --tag-list "docker,linux"

Then verify registration:

sudo gitlab-runner verify

Expected output:

Runtime platform                                    arch=amd64 os=linux pid=1234 revision=4b5e6f1 version=16.11.0
Running in system-mode.

Verifying runner... is alive                        runner=abc123

Recovery: If the runner does not appear in the GitLab UI, check /etc/gitlab-runner/config.toml for the correct URL and token, then run gitlab-runner restart.

3. Move a runner between groups/projects safely

Changing a runner's scope requires de-registering and re-registering. This disrupts running jobs on that runner. Plan maintenance windows accordingly.

  1. Pause the runner in GitLab UI (Admin > Runners > click runner > Pause).
  2. Wait for any active jobs to finish.
  3. Unregister the runner from the old scope via API or UI.
  4. Re-register with the new scope token.
  5. Unpause and verify.

4. Use CI/CD variables securely

Protect secrets using masked and protected variables. In GitLab UI: Settings > CI/CD > Variables > Add variable.

  • Key: AWS_SECRET_ACCESS_KEY
  • Value: dummy-value-123 (replace with real secret from your vault)
  • Mask variable: yes
  • Protect variable: yes (only on protected branches/tags)

In .gitlab-ci.yml, reference it without echoing:

deploy:
  script:
    - aws s3 cp build s3://my-bucket --region us-east-1

Never use echo $AWS_SECRET_ACCESS_KEY in logs. GitLab masks variables that match certain patterns, but it is not bulletproof.

Verification and Diagnostics

After making a change, verify that the system behaves as expected. Use read-only commands and API queries.

1. View pipeline status for a commit

Use the pipelines API to get the status of a pipeline for a specific commit SHA.

curl --header "PRIVATE-TOKEN: <your_pat>" \
  "https://gitlab.example.com/api/v4/projects/123/pipelines?sha=<commit_sha>"

Expected response (simplified):

[
  {
    "id": 7654,
    "status": "success",
    "ref": "main",
    "sha": "abcdef123456",
    "web_url": "https://gitlab.example.com/group/project/-/pipelines/7654"
  }
]

2. Fetch job logs for a failed job

When a pipeline fails, identify the failed job and pull logs via API:

# First list jobs for pipeline 7654
curl --header "PRIVATE-TOKEN: <your_pat>" \
  "https://gitlab.example.com/api/v4/projects/123/pipelines/7654/jobs"

# Then get the trace for a specific job id (e.g., 98765)
curl --header "PRIVATE-TOKEN: <your_pat>" \
  "https://gitlab.example.com/api/v4/projects/123/jobs/98765/trace" > job_98765.log

Inspect the log:

grep -n "ERROR" job_98765.log

Common error patterns:

  • fatal: unable to access 'https://gitlab.example.com/...': The requested URL returned error: 403 -> check runner network or credentials.
  • ERROR: Job failed (system failure): Error response from daemon: pull access denied -> Docker image private or wrong credentials.

3. Monitor runner health

Check runner concurrency and offline runners from the API:

curl --header "PRIVATE-TOKEN: <your_admin_pat>" \
  "https://gitlab.example.com/api/v4/runners/all?status=online"

Compare with your expected runner pool. If a runner is offline, check the runner host:

sudo gitlab-runner status
sudo gitlab-runner list

4. Verify configuration with CI Lint

Always lint the entire pipeline after changes. The API accepts include paths and returns the merged YAML.

curl --header "Content-Type: application/json" \
     --header "PRIVATE-TOKEN: <your_pat>" \
     --data '{"content": "include:\n  - project: group/templates\n    ref: main\n    file: /ci/base.yml\n\nstages:\n  - build\n\nbuild_job:\n  stage: build\n  script: echo hello"}' \
     "https://gitlab.example.com/api/v4/ci/lint"

Failure Modes and Recovery

Even careful changes can go wrong. Know the common failure modes and how to recover without making things worse.

Failure: Authentication failure when registering runner

Symptom: ERROR: Registering runner... forbidden (check registration token)

Why: Registration token expired, revoked, or you are using a personal access token instead of a runner registration token.

Recovery:

  1. Obtain a fresh registration token from GitLab UI (Settings > CI/CD > Runners > Register a group runner or project runner).
  2. Ensure the token is copied exactly, without trailing spaces.
  3. If using an authentication token (newer method), create it via API:
   curl --request POST --header "PRIVATE-TOKEN: <your_pat>" \
     "https://gitlab.example.com/api/v4/user/runners" \
     --data "runner_type=project_type&project_id=123&description=my-runner"

The response contains a token field. Use that token with gitlab-runner register --token <token>.

Failure: Pipeline stuck in pending

Symptom: Pipeline shows pending for a long time, no runner picks it up.

Possible causes:

  • No active runner with matching tags.
  • Runner is offline or paused.
  • Runner concurrency limit reached.
  • Runner not assigned to the project/group.

Diagnostic steps:

  1. List runners for the project:
   curl --header "PRIVATE-TOKEN: <your_pat>" \
     "https://gitlab.example.com/api/v4/projects/123/runners"

Check active: true and online: true.

  1. Check runner tags. If job has tags: [docker, linux], ensure a runner has both tags.
  2. Check runner concurrency in /etc/gitlab-runner/config.toml:
   concurrent = 2

Increase if needed, then restart runner.

  1. If no runner available, register a new one or enable a shared runner.

Failure: Secret leaked in job logs

Symptom: A masked variable appears unmasked or a secret is accidentally echoed.

Why: The variable did not meet masking requirements (no spaces, length >8, not a known pattern) or you explicitly printed it.

Recovery:

  1. Immediately revoke the secret (e.g., rotate AWS key, reset password).
  2. Edit the job to remove the echo statement.
  3. Purge job logs if necessary via API (admin only):
   curl --request DELETE --header "PRIVATE-TOKEN: <your_admin_pat>" \
     "https://gitlab.example.com/api/v4/projects/123/jobs/98765/artifacts"
  1. Review CI/CD variables: remove unused secrets, enforce masking.

Operations Checklist

Use this checklist before and after any CI/CD change. Assign an owner to each item and review it monthly.

#CheckCommand / APIExpectedOwnerFrequency
1GitLab version supportedsudo gitlab-rake gitlab:env:infoVersion matches supported matrixDevOps leadMonthly
2Runner versions match GitLabgitlab-runner --version on each runnerRunner version within one major of GitLabCI adminMonthly
3All runners onlinecurl --header "PRIVATE-TOKEN: <pat>" "https://gitlab.example.com/api/v4/runners/all?status=online"No unexpected offline runnersCI adminWeekly
4CI config validcurl ... /ci/lint with latest config"valid": truePipeline ownerBefore every merge
5Secrets are maskedReview CI/CD variables in UIAll secrets masked and protectedSecurity officerQuarterly
6Pipeline success rateProject CI/CD analytics>90% success on mainProject ownerMonthly
7Runner concurrency sufficientgrep concurrent /etc/gitlab-runner/config.tomlNo jobs waiting >5 minCI adminMonthly
8Backup of gitlab-ci.yml and runner configsVersion control + config backupConfig can be restored in under 15 minConfiguration managerWeekly

Owner note: For each item, one named individual is accountable, not a team. They should receive alerts and review the check on the stated frequency. Update this checklist as your environment evolves.

Common Pitfalls and How to Avoid Them

Pitfall 1: Using the wrong token type

Why it happens: GitLab has many token types: personal access, project access, group access, runner registration, runner authentication, deploy tokens. Mixing them leads to authentication failures.

How to avoid: Always check the API docs for required token type and scopes. Use dedicated service accounts with least privilege.

Recovery: If you receive 401/403, verify token scope and expiration. Create a new token with correct permissions.

Pitfall 2: Hardcoding secrets in .gitlab-ci.yml

Why it happens: Developers want quick fixes and sometimes embed passwords directly.

How to avoid: Use CI/CD variables (Settings > CI/CD > Variables) and never commit secrets. Enable secret detection in pipeline.

Recovery: If secret is committed, treat it as compromised: rotate immediately, remove from git history, and re-encrypt any affected data.

Pitfall 3: Editing runner config while jobs are running

Why it happens: Trying to fix a runner without pausing it first.

How to avoid: Pause the runner in UI, wait for jobs to finish, then modify config.

Recovery: If a runner becomes inconsistent, re-register it from scratch after unregistering.

Pitfall 4: Not pinning Docker image versions

Why it happens: Using image: latest or floating tags leads to unpredictable builds.

How to avoid: Pin to a specific version like image: alpine:3.19.1. Use Dependabot or scheduled pipelines to update pinned versions.

Recovery: Roll back to previous known-good image tag in the pipeline definition.

Conclusion

GitLab CI/CD basic commands are only useful when they are version-scoped, observable, and reversible. Copying a command without checking prerequisites and expected output is not an operations procedure; it is gambling.

As a next step, choose one low-risk verification from this guide: check your GitLab and runner versions, lint your CI config, or list your runners. Record the current state, run the documented check, compare the result with the expected signal, and note any gaps in your recovery plan.

A reliable technical workflow makes failure visible, protects sensitive values, limits changes to the intended resource, and defines recovery verification before an incident forces the decision. Use this guide as your day-to-day cheat sheet, and revisit it whenever your environment or GitLab version changes.

Related Research

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL