Installing Continuous Deployment on Ubuntu with GitLab
What will you learn in this guide?
In this guide
oaicite:0
With CI/CD
**
oaicite:1
**on a working server
**
oaicite:2
You will establish a **based automatic distribution line.
After each commit, you will learn the process of producing a Docker image, sending it to the registry, and going live via SSH.
We will set up a production-ready CD structure used in real life, including rollback.
Stage 1 – Technical Analysis (Summary)
Main topic: Installing Continuous Deployment with GitLab CI/CD
Solved problem: Manual deployment, human error and waste of time
Steps followed:
- Creating a GitLab repo
- Installing GitLab Runner
- Deploy securely via SSH
- Producing and running a Docker image
- Rollback
Prerequisites
- Ubuntu 18.04 or above server
- At least 1 GB RAM, 1 CPU
- Docker must be installed on the server
- Container Registry is an open GitLab account
sudoauthorized, non-root user
Creating a GitLab Project
In GitLab, select New Project → Blank Project.
Set the project name and adjust visibility as needed.
Creating index.html
<html>
<body>
<h1>My Personal Website</h1>
</body>
</html>
- This file is the sample web page that will be displayed in the browser after deployment.
Creating Dockerfile
- Dockerfile
COPY index.html /usr/share/nginx/html
- This Dockerfile adds static site on Nginx image. Using a fixed version is good practice to avoid surprises in the future.
GitLab Runner Installation
- Connect to the server:
ssh deployer@SUNUCU_IP
- Install GitLab Runner:
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install gitlab-runner
- This service runs CI/CD jobs.
- Save the Runner to the project:
sudo gitlab-runner register -n \
--url https://gitlab.com \
--registration-token PROJE_TOKEN \
--executor docker \
--docker-image docker:stable \
--tag-list deployment \
--docker-privileged
- This runner only deploys for this project.
Creating Deployment User
sudo adduser deployer
sudo usermod -aG docker deployer
- This user is used only for deployment operations.
(Yes, the Docker group is as authorized as root — we do it on purpose.)
Generating SSH Key
su deployer
ssh-keygen -b 4096
- cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
- CI/CD pipeline connects to the server with this key.
Password is left blank; pipeline is not interactive.
Saving SSH Key to GitLab
- GitLab → Settings → CI/CD → Variables
| Key | Type | Description |
|---|---|---|
| ID_RSA | Net | SSH private key |
| SERVER_IP | Variable | Server IP |
| SERVER_USER | Variable | deployer |
ID_RSA variable must be marked as Protected.
.gitlab-ci.yml File
stages:
- publish
- deploy
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
publish:
image: docker:latest
stage: publish
services:
- docker:dind
script:
- docker build -t $TAG_COMMIT -t $TAG_LATEST .
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker push $TAG_COMMIT
- docker push $TAG_LATEST
deploy:
image: alpine:latest
stage: deploy
tags:
- deployment
script:
- chmod og= $ID_RSA
- apk add --no-cache openssh-client
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker pull $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker rm -f my-app || true"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d -p 80:80 --name my-app $TAG_COMMIT"
environment:
name: production
url: http://SUNUCU_IP
only:
- master
- This structure produces the Docker image and automatically goes live.
Deploy Verification
- GitLab → CI/CD → Pipelines
- Pipeline status must be Passed.
- Check from browser:
http://SUNUCU_IP
- Verify container on server:
docker ps
- my-app container must be running.
Rollback
-
Click Run Again for old deployment
-
GitLab redeploys the old image
-
Live system returns to its previous state
Frequently Asked Questions (FAQ)
1. Is this structure suitable for production? Yes, it is very suitable for small and medium-sized projects.
2. Are there other methods instead of SSH? Yes, Kubernetes or GitOps may be preferred.
3. Can I use Shared Runner? Not recommended for security reasons.
4. How to add HTTPS? Nginx + Let's Encrypt or Traefik can be used.
5. Why does rollback fail? The old image may have been deleted from the registry.
Result
With this guide, you've set up a fully automated deployment chain using GitLab CI/CD. After each commit, your application is published automatically.
You can implement this structure in minutes on the GenixNode infrastructure.

