Getting Started with GitLab CI/CD: Pipelines, Runners, and SSH Deployment
This guide introduces GitLab CI/CD by explaining pipelines, jobs, stages, runner registration, and SSH‑based deployment, providing a complete example .gitlab-ci.yml and Docker‑based runner setup for beginners who want to automate build, test, and release processes.
Pipeline Overview
The purpose of this article is to give a friendly introduction to GitLab CI/CD through a sample application, allowing newcomers to start 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 extends CI by automatically deploying the application to a production environment whenever code is pushed to the default branch, helping catch errors early and ensuring all deployed code meets defined standards.
One major benefit of GitLab CI/CD is that it requires no third‑party plugins: the workflow is defined in a .gitlab-ci.yml file placed at the repository root, and the scripts are executed by a GitLab Runner.
Scripts are organized into jobs that together form a pipeline . Jobs are grouped into stages , and the order of stages determines execution order.
Example Pipelines
Project Pipeline : installs dependencies, runs linters, and processes the code.
Continuous Integration Pipeline : runs automated tests and builds a distributable version.
Deployment Pipeline : deploys the code to a chosen cloud provider and environment.
Below 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."The three stages are build , test , and deploy ; each stage contains the jobs listed above. Jobs are executed in the order defined by the stages keyword.
You can use the only keyword to restrict jobs, for example deploying to a staging server with one job and to production with another:
deploy-production:
stage: deploy
script:
- ./deploy_prod.sh
only:
- masterNote: Pipeline job 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 templates.
GitLab Runner
GitLab Runner is an open‑source project that runs your jobs and reports results back to GitLab. It works with GitLab CI/CD, which is the built‑in continuous integration service.
Runners can be installed on GNU/Linux, macOS, FreeBSD, or Windows, and you can run them via Docker, a binary download, or package repositories (rpm/deb).
To run a gitlab-runner container, ensure Docker is installed and start the container with an Alpine image:
docker run --rm -it -v /srv/gitlab-runner/config:/etc/gitlab-runner gitlab/gitlab-runner registerIf you need the session_server , expose port 8093:
docker run -p 8093:8093 ...Registering a runner involves three steps:
Run the register command (as shown above).
Enter the GitLab instance URL (e.g., https://gitlab.com).
Provide the registration token found under Settings → CI/CD → Runners.
After registration, the runner’s configuration is stored in a volume (e.g., /srv/gitlab-runner/config ) and automatically loaded on start.
Deployment Method (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 (do not set a passphrase to avoid prompts in before_script ):
ssh-keygen -t rsa -b 4096 -C "example"Copy the public key to authorized_keys on the target server and add the private key as a CI/CD variable named SSH_PRIVATE_KEY .
# Copy the content of public key to authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
# Show private key content
cd .ssh && cat id_rsaIn the GitLab UI, go to Settings → CI/CD → Variables and add SSH_PRIVATE_KEY with the private key value.
Example deployment pipeline that uses an Alpine image, installs the SSH client, adds the private key to the agent, and runs an SSH command:
# 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) # Start the SSH agent
- 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:
- masterAlpine does not include an SSH client by default, which is why the apk add openssh-client step is necessary.
DevOps Cloud Academy
Exploring industry DevOps practices and technical expertise.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.