Operations 12 min read

A Beginner’s Guide to GitLab CI/CD Pipelines, Runner Setup, and SSH Deployment

This article provides a comprehensive, step‑by‑step guide to setting up GitLab CI/CD pipelines, configuring .gitlab-ci.yml files, registering Docker‑based GitLab Runners, and deploying applications via SSH, covering stages, jobs, and practical code examples for DevOps practitioners.

DevOps Cloud Academy
DevOps Cloud Academy
DevOps Cloud Academy
A Beginner’s Guide to GitLab CI/CD Pipelines, Runner Setup, and SSH Deployment

The purpose of this tutorial is to give a friendly, hands‑on introduction to GitLab CI/CD using a sample application, so readers can get started without reading the entire GitLab documentation.

Continuous Integration works by pushing small code commits to a Git repository; each push triggers a pipeline that builds, tests, and validates the changes before merging into the main branch. Continuous Delivery/Deployment adds a further CI step that automatically deploys the application to a production environment on every push to the default branch.

One of the main benefits of GitLab CI/CD is that the entire workflow is defined in a single .gitlab-ci.yml file placed at the repository root, and the scripts are executed by a GitLab Runner.

Jobs are grouped into stages to form a pipeline . The tutorial defines three example pipelines:

Project Pipeline : installs dependencies, runs linters, and processes all code.

Continuous Integration Pipeline : runs automated tests and builds a distributable version.

Deployment Pipeline : deploys the code to a chosen cloud provider and environment.

The following is a basic .gitlab-ci.yml example that defines three stages (build, test, deploy) and several jobs:

stages:
  - build
  - test
  - deploy

image: alpine

build_a:
  stage: build
  script:
    - echo "This job builds something."

build_b:
  stage: build
  script:
    - echo "This job builds something else."

test_a:
  stage: test
  script:
    - echo "This job tests something. It will only run when all jobs in the"
    - echo "build stage are complete."

test_b:
  stage: test
  script:
    - echo "This job tests something else. It will only run when all jobs in the"
    - echo "build stage are complete too. It will start at about the same time as test_a."

deploy_a:
  stage: deploy
  script:
    - echo "This job deploys something. It will only run when all jobs in the"
    - echo "test stage complete."

deploy_b:
  stage: deploy
  script:
    - echo "This job deploys something else. It will only run when all jobs in the"
    - echo "test stage complete. It will start at about the same time as deploy_a."

Jobs are executed in the order defined by the stages keyword. The only directive can be used to run specific jobs (e.g., deploying to a staging server vs. production) when commits are pushed to particular branches.

deploy-production:
  stage: deploy
  script:
    - ./deploy_prod.sh
  only:
    - master

Pipeline names are customizable; you can rename deploy-production to any meaningful identifier.

Before adding the YAML file to the repository root, you can validate it with the CI Lint tool or start from one of the UI‑provided templates.

GitLab Runner

GitLab Runner is an open‑source project that executes jobs and reports results back to GitLab. It can run on GNU/Linux, macOS, FreeBSD, and Windows, and can be installed via Docker, binary download, or package manager.

To run a gitlab-runner inside a Docker container, ensure Docker is installed and use an Alpine image:

docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner register

During registration you will be prompted for the GitLab coordinator URL and a registration token (obtainable from Settings → CI/CD → Runners → Expand → Manual registration ).

Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com)
https://gitlab.com

Please enter the gitlab-ci token for this runner
xxx

After registration the configuration is written to the chosen volume (e.g., /srv/gitlab-runner/config ) and automatically loaded by the Runner.

Deployment via SSH

When CI/CD jobs run inside Docker containers and need to deploy to a private server, you must provide SSH access. Generate an SSH key pair (without a passphrase) and add the private key as a CI/CD variable named SSH_PRIVATE_KEY .

ssh-keygen -t rsa -b 4096 -C "example"
# Copy the content of public key to authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
cd .ssh && cat id_rsa

Add the private key value in Settings → CI/CD → Variables → Expand . Also add a deployment key (read‑only or read‑write) in Settings → Repository → Deploy Keys → Expand by pasting the public key ( id_rsa.pub ).

# Includes deployment pipeline only
image: alpine:3.7
stages:
  - deploy

before_script:
  ## Optionally set Git user info if needed
  #- git config --global user.email "[email protected]"
  #- git config --global user.name "User name"

deploy_production:
  stage: deploy
  before_script:
    - apk add openssh-client # Add SSH client for alpine
    - eval $(ssh-agent -s) # Run the SSH client
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
  script:
    - ssh -o StrictHostKeyChecking=no username@host_ip_address "cd /project && git pull"
  only:
    - master

Because Alpine does not include an SSH client by default, the pipeline installs it via apk add openssh-client . Adjust commands if you use a different base image.

About the Author

Ze Yang, a DevOps practitioner focusing on enterprise‑level DevOps operations and Linux administration, shares practical courses and tutorials.

DockerDevOpsYAMLGitLab CI/CDSSH DeploymentCI Pipeline
DevOps Cloud Academy
Written by

DevOps Cloud Academy

Exploring industry DevOps practices and technical expertise.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.