Simple Gitlab CI/CD pipline example

in #hive-163521yesterday

Good day dear mates with this post I'd like to open series about CI/CD, IAC and server related topics which I've already mentioned in my post about my New Year's resolutions Of course maybe not all of my posts will go in timeline order or from easy to hard order but all of them I'll put in the tail at the bottom of this series posts.

изображение.png


Also please consider that most of this let's call it tutorials will be created using mostly Yandex cloud and other availiable for me platforms. And please remember that in current moment ASW,Azure, Google cloud are mostly unavailable for me.


Another one important point that if you have suggestions or critic for steps in this series I'll be glad if you add them in comment section and I'll of course change or update posts if it'll be necessary. The next one important thing that steps from this tutorial you can repeat with VPS created on any other available for you service! And yes I remember about security but for more clearance I'll show some private keys and creds which were created for showcase.


Intro

In first post I'd like to write just a simple example of CI/CD pipline with gitlab. Here I think that it's needed to separate tutorial for several sections.
It's creating gitlab project where will be highlighted not only just a simple creation of project but registration of gitlab runner.
In other one section I'd like to describe how to create VM - virtual mashine on Yandex cloud ( for example) adding ssh keys to it.
Another one section to create simple .gitlab-ci.yaml file. And just an example files of index.html and Dockerfile.
And of course I'll describe how to add variables to gitlab pipeline settings.
So let's start!


Creating VMs on Yandex cloud and adding ssh keys

For this post where I describe how to implement CI-CD for us will be needed two VPS. First of them we'll use as a Gitlab runner and the second one we'll use to deploy example app.
As so as I use for it Yandex cloud to creat VPS I'll describe some steps more detail. So you need to select Create virtual server Then needed to choose OS, zone of availability, type of hard disk.To reduce cost it's better to take HDD coz it's not critical for Gitlab runner. At resource section you can choose Shared-core and minimize availability to 20% or 50% and number of CPU and RAM.

Снимок экрана от 2025-01-09 18-17-37.png

Then choose access via ssh-key. After what add username which you'll use to login and public part of shh-key which can be get with command

cat ~/.ssh/id_rsa.pub

Снимок экрана от 2025-01-09 18-17-56.png


Снимок экрана от 2025-01-09 18-19-10.png

Then push create VM and whait until provisioning will be finished.

Снимок экрана от 2025-01-09 18-26-55.png

Copy ip addres and with command shown bellow you can get access to your VM via ssh.

ssh -l admin 84.252.129.182

The same algorithm you can use to create second Virtual Machine for deploy our example app.

Creating Gitlab project

Now let's create new Gitlab project for our app. For it login to your Gitlab account. And push on the left side + and choose New project.

Снимок экрана от 2025-01-09 18-26-55.png

After what select Blanck project.

Снимок экрана от 2025-01-09 18-27-15.png

Then fulfill name of your project and choose private or public project you want to create.

Снимок экрана от 2025-01-09 18-28-04.png

And then you'll get new repository for our example app. Next you'll need to add files to our repo, for it just push +
Снимок экрана от 2025-01-09 18-41-06.png

Registration of Gitlab runner on Yandex cloud VPS

Navigae at the left side menu to Settings.

Снимок экрана от 2025-01-09 18-44-13.png

Choose there RUNNERS

Снимок экрана от 2025-01-09 18-44-38.png

and then New project runner

Снимок экрана от 2025-01-09 18-45-19.png

Now about creation of runners. You can create it by following Gitlab docs and create it containers. But I'll use simple runner. For it possible to follow runner installation and registration instructions or just use simple command which you'll find in HINT section at the end of this paragraph.

Push Show runner installation and registration instructions

Снимок экрана от 2025-01-09 18-45-52.png
And you'll see instructions how to register new runner for your project.

Снимок экрана от 2025-01-09 18-46-07.png

First of all you need to login via ssh to our VPS with command

ssh -l admin 84.252.129.182

Update it, remember we created new VPS.
Download the binary for your system

sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

Give it permission to execute

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

Create a GitLab Runner user

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

Install and run as a service

sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner

sudo gitlab-runner start

Снимок экрана от 2025-01-09 18-57-22.png

Check status of gitlab-runner

systemctl status gitlab-runner

Снимок экрана от 2025-01-09 18-58-57.png

Command to register runner

sudo gitlab-runner register --url https://gitlab.com/ --registration-token GR1348941guiLEF9rnziZ7xz6s1zd

Снимок экрана от 2025-01-09 19-21-01.png

Also then you'll need to enter additional info like address of gitlab - https://gitlab.com/, registration-token GR1348941guiLEF9rnziZ7xz6s1zd , type of executor docker name of image
stable

Снимок экрана от 2025-01-09 19-22-06.png

example of config runner file you can find in /etc/gitlab-runner/config.toml

Снимок экрана от 2025-01-09 19-24-39.png

HINT

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt-get install gitlab-runner
systemctl status gitlab-runner
sudo gitlab-runner register --name My_demo_runner --url https://gitlab.com --token GR1348941guiLEF9rnziZ7xz6s1zd --executor docker --description "Deployment Runner" --docker-image docker:stable --non-interactive

Also you can add to command options --tag-list option and --docker-privileged and it'll looks like

sudo gitlab-runner register --name My_demo_runner --url https://gitlab.com --token GR1348941guiLEF9rnziZ7xz6s1zd --executor docker --description "Deployment Runner" --docker-image docker:stable --tag-list deployment --docker-privileged --non-interactive

Config of registered Gitlab runner you can find at

/etc/gitlab-runner/config.toml

Index.html & Dockerfile

In index.html I just put simple html code for this tutorial

<html>
    <body>
        <h1>My Personal Website</h1>
    </body>
</html>

Снимок экрана от 2025-01-09 18-42-19.png

And just a simple Dockerfile for simplifying it consists of 2 strings where The FROM instruction determinates the image to inherit from in our case it's nginx server with tag 1.18 image version. Also if you'd like you can use a latest tag what references the latest Nginx release.
The COPY instruction copies index.html file to /usr/share/nginx/html in the Docker image. This is the directory where Nginx stores static HTML content.

FROM nginx:1.18
COPY index.html /usr/share/nginx/html

Снимок экрана от 2025-01-09 18-43-16.png

As a result we'll have index.html file, Dockerfile, and Readme.MD

Снимок экрана от 2025-01-09 18-43-51.png
Then we need to add .gitlab-ci.yaml file.


.gitlab-ci.yaml file

In this section you'll find example of simple .gitlab-ci.yaml file where we have just two stages. First of them just build the Docker image and push it to container register. And another one log in to our VPS and deploy there our index.html page.

stages:
  - build
  - 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 update && apk add openssh-client
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker container rm -f my-app || true"
    - ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d -p 80:80 --name example-app $TAG_COMMIT"
  environment:
    name: production
    url: http://51.250.7.160
  only:
    - main

Heere I commented tags section coz it's not needed now for but you can untag it if you want to make some more settings for your pipieline.


Installing Docker on VPS

As so as I choose VPS with preinstalled Ubuntu OS I used this commands which i took from official site to install Docker on VPS. And here is the address for reference https://docs.docker.com/engine/install/ubuntu/

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Install latest version

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Also you'll need to add user to docker. To create the docker group and add your user.
First create the docker group.

sudo groupadd docker

Add your user to the docker group you can via one of this commands

sudo usermod -aG docker admin

or

sudo usermod -aG docker ${USER}

then

su -s ${USER}

Hint
This permits admin user to execute the docker command, which is required to perform the deployment.
Adding a user to the Docker group, grants privileges equivalent to the root user. For more details on how this has an impact on security in your system, see Docker Daemon Attack Surface.


Adding variables

To deploy our app to the second VPS we'll need private part of ssh-key, ip address of VPS and name which we'll use to login.

Navigate to SETTINGS -> CI/CD -> Variables And Add variable SERVER_IP with type Variable, Key: SERVER_IP Value: 51.250.7.160(change for your server IP) Environment scope: All (default) Protect variable: Checked Mask variable: Checked or for example I put it Visible.

Also you need to add Variable
Key: ID_RSA
Value: Paste your SSH private key from your clipboard (including a line break at the end) /n
Type: File
Environment Scope: All (default)
Protect variable: Checked
Mask variable: Unchecked

-----BEGIN OPENSSH PRIVATE KEY-----
your_private_key
-----END OPENSSH PRIVATE KEY-----
/n

Get private part of your ssh- key you can with:

cat ~/.ssh/id_rsa

And finally we need to add a variable with the login user

Key: SERVER_USER
Value: admin
Type: Variable
Environment scope: All (default)
Protect variable: Checked
Mask variable: Checked

When all is ready you just need to commit some changes in your code for example in index.html and push them to gitlab after what pipiline will start automatically and you see new jobs in Build -> Jobs You can move inside Job and if all was done correctly you'll see that jood was succeed!

Снимок экрана от 2025-01-12 00-59-41.png

Fix possible errors

In my case when I tryed to start pipline first time on new VPS I got error like

admin@51.250.7.67: Permission denied (publickey)

Снимок экрана от 2025-01-12 01-01-25.png

Top fix it I changed parameter PubkeyAuthentication to yes in sshd_config file wih command

sudo nano /etc/ssh/sshd_config

And then after saved it restarted sshd

sudo systemctl restart sshd

Снимок экрана от 2025-01-12 01-02-41.png

So that's all for now. Stay tuned! Yours @travoved