Press "Enter" to skip to content

HOW-TO Build CICD with Gitlab

Pre-Check

  • I will guide you to build a CICD pipeline on your private Gitlab environment. We will deploy the index.html on node1 /var/www/html.
  • In this sample, we need three servers as below:
Node(Hostname) IP Network Privilege Description
cicd 192.168.70.4 Gitlab & node1 reachable runner server
node1 192.168.70.5 cicd node reachable will deploy a static html on this server
gitlab 192.168.70.6 cicd node reachable Gitlab server
root@gitlab:~# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:    24.04
Codename:   noble

root@gitlab:~# uname -r
6.8.0-40-generic

root@gitlab:~# cat /etc/hosts
127.0.0.1 localhost
192.168.70.4 cicd
192.168.70.5 node1
192.168.70.6 gitlab

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Gitlab server install guide

Preparation

  • Create a project->Create a blank project
  • Create the webpage project
  • Settings->CICD->Runners->New project runner
  • Input ‘Tags’ and select ‘Run untagged jobs’->Create runner
  • Install runner on cicd server
## run on cicd server
## add & configure gitlab-runner apt resource
➜  ~ curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  6885  100  6885    0     0  16455      0 --:--:-- --:--:-- --:--:-- 16431
Detected operating system as Ubuntu/noble.
Checking for curl...
Detected curl...
Checking for gpg...
Detected gpg...
Running apt-get update... done.
Installing apt-transport-https... done.
Installing /etc/apt/sources.list.d/runner_gitlab-runner.list...done.
Importing packagecloud gpg key... done.
Running apt-get update... done.

The repository is setup! You can now install packages.

## install gitlab-runner
➜  ~ apt install gitlab-runner -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Suggested packages:
  docker-engine
The following NEW packages will be installed:
  gitlab-runner
0 upgraded, 1 newly installed, 0 to remove and 4 not upgraded.
Need to get 494 MB of archives.
After this operation, 541 MB of additional disk space will be used.
Get:1 https://packages.gitlab.com/runner/gitlab-runner/ubuntu noble/main arm64 gitlab-runner arm64 17.2.1-1 [494 MB]
Fetched 494 MB in 14s (34.1 MB/s)
Selecting previously unselected package gitlab-runner.
(Reading database ... 132449 files and directories currently installed.)
Preparing to unpack .../gitlab-runner_17.2.1-1_arm64.deb ...
Unpacking gitlab-runner (17.2.1-1) ...
Setting up gitlab-runner (17.2.1-1) ...
GitLab Runner: detected user gitlab-runner
Runtime platform                                    arch=arm64 os=linux pid=11020 revision=9882d9c7 version=17.2.1
gitlab-runner: the service is not installed
Runtime platform                                    arch=arm64 os=linux pid=11028 revision=9882d9c7 version=17.2.1
gitlab-ci-multi-runner: the service is not installed
Runtime platform                                    arch=arm64 os=linux pid=11050 revision=9882d9c7 version=17.2.1
Runtime platform                                    arch=arm64 os=linux pid=11148 revision=9882d9c7 version=17.2.1

Check and remove all unused containers (both dangling and unreferenced)
-----------------------------------------------------------------------
Total reclaimed space: 0B
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
  • Can find the url & token on current page to configure the gitlab-runner. As cicd server is ubuntu, will run shell script to deploy on node1. So, select shell as executor here.
## configure gitlab-runner
➜  ~ gitlab-runner register
Runtime platform                                    arch=arm64 os=linux pid=11306 revision=9882d9c7 version=17.2.1
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
http://192.168.70.6
Enter the registration token:
glrt-DgMGM6YiWmnpa_8srLrv
Verifying runner... is valid                        runner=DgMGM6YiW
Enter a name for the runner. This is stored only in the local config.toml file:
[cicd]:
Enter an executor: instance, shell, ssh, parallels, virtualbox, docker-windows, kubernetes, docker-autoscaler, custom, docker, docker+machine:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
  • Start and check the gitlab-runner service.
## restart service
➜  ~ systemctl restart gitlab-runner.service

## check service status
➜  ~ systemctl status gitlab-runner.service
● gitlab-runner.service - GitLab Runner
     Loaded: loaded (/etc/systemd/system/gitlab-runner.service; enabled; preset: enabled)
     Active: active (running) since Sun 2024-08-11 22:19:52 HKT; 5s ago
   Main PID: 11350 (gitlab-runner)
      Tasks: 7 (limit: 4550)
     Memory: 18.5M (peak: 19.0M)
        CPU: 40ms
     CGroup: /system.slice/gitlab-runner.service
             └─11350 /usr/bin/gitlab-runner run --working-directory /home/gitlab-runner --config /etc/gitlab-runner/config.toml --service gitlab-runner --user gitlab-runner

Aug 11 22:19:52 cicd systemd[1]: Started gitlab-runner.service - GitLab Runner.
Aug 11 22:19:52 cicd gitlab-runner[11350]: Runtime platform                                    arch=arm64 os=linux pid=11350 revision=9882d9c7 version=17.2.1
Aug 11 22:19:52 cicd gitlab-runner[11350]: Starting multi-runner from /etc/gitlab-runner/config.toml...  builds=0 max_builds=0
Aug 11 22:19:52 cicd gitlab-runner[11350]: Running in system-mode.
Aug 11 22:19:52 cicd gitlab-runner[11350]:
Aug 11 22:19:52 cicd gitlab-runner[11350]: Configuration loaded                                builds=0 max_builds=1
Aug 11 22:19:52 cicd gitlab-runner[11350]: listen_address not defined, metrics & debug endpoints disabled  builds=0 max_builds=1
Aug 11 22:19:52 cicd gitlab-runner[11350]: [session_server].listen_address not defined, session endpoints disabled  builds=0 max_builds=1
Aug 11 22:19:52 cicd gitlab-runner[11350]: Initializing executor providers                     builds=0 max_builds=1
  • Click ‘View runners’ on button of the page.
  • Now can find the runner already online.
  • Generate ssh key on cicd server
## run on cicd server
## switch to gitlab-runner
➜  ~ su - gitlab-runner

## generate ssh key
gitlab-runner@cicd:~$ ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/gitlab-runner/.ssh/id_ed25519):
Created directory '/home/gitlab-runner/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/gitlab-runner/.ssh/id_ed25519
Your public key has been saved in /home/gitlab-runner/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:LAAffh30pXEi/ffvJQ4MMqmx1OrCmtiHvA5JWX0spUc gitlab-runner@cicd
The key's randomart image is:
+--[ED25519 256]--+
|  . .  E+.o o    |
|   +..=. +.*     |
|   .++.+. o.     |
|  o  o+o .  . .  |
| o    + S .  . . |
|..   . * o o    .|
|o. o  +     o . o|
| +o.+.       o .o|
|..*+ ..       ...|
+----[SHA256]-----+

## get the public key
gitlab-runner@cicd:~$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJmJzEnxn3ehueLDYy7/ZmoPhK3ANNfzxfmJ7zZzTgut gitlab-runner@cicd

  • Switch to browser and click on the left top avatar->Preferences
  • SSH Key->Add new key->Paste the public key content in the blank->Add Key.
  • Switch to node1 console to install apache2
## run on node1 server
## install apache2
root@node1:~# apt install apache2 -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  apache2-bin apache2-data apache2-utils libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 liblua5.4-0 ssl-cert
Suggested packages:
  apache2-doc apache2-suexec-pristine | apache2-suexec-custom www-browser
The following NEW packages will be installed:
  apache2 apache2-bin apache2-data apache2-utils libapr1t64 libaprutil1-dbd-sqlite3 libaprutil1-ldap libaprutil1t64 liblua5.4-0 ssl-cert
0 upgraded, 10 newly installed, 0 to remove and 4 not upgraded.
Need to get 2,064 kB of archives.
After this operation, 14.0 MB of additional disk space will be used.
Get:1 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 libapr1t64 arm64 1.7.2-3.1build2 [105 kB]
Get:2 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 libaprutil1t64 arm64 1.6.3-1.1ubuntu7 [93.9 kB]
Get:3 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 libaprutil1-dbd-sqlite3 arm64 1.6.3-1.1ubuntu7 [11.2 kB]
Get:4 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 libaprutil1-ldap arm64 1.6.3-1.1ubuntu7 [9,046 B]
Get:5 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 liblua5.4-0 arm64 5.4.6-3build2 [158 kB]
Get:6 http://ports.ubuntu.com/ubuntu-ports noble-updates/main arm64 apache2-bin arm64 2.4.58-1ubuntu8.4 [1,319 kB]
Get:7 http://ports.ubuntu.com/ubuntu-ports noble-updates/main arm64 apache2-data all 2.4.58-1ubuntu8.4 [163 kB]
Get:8 http://ports.ubuntu.com/ubuntu-ports noble-updates/main arm64 apache2-utils arm64 2.4.58-1ubuntu8.4 [96.3 kB]
Get:9 http://ports.ubuntu.com/ubuntu-ports noble-updates/main arm64 apache2 arm64 2.4.58-1ubuntu8.4 [90.2 kB]
Get:10 http://ports.ubuntu.com/ubuntu-ports noble/main arm64 ssl-cert all 1.1.2ubuntu1 [17.8 kB]
Fetched 2,064 kB in 6s (347 kB/s)
Preconfiguring packages ...
Selecting previously unselected package libapr1t64:arm64.
(Reading database ... 129721 files and directories currently installed.)
Preparing to unpack .../0-libapr1t64_1.7.2-3.1build2_arm64.deb ...
Unpacking libapr1t64:arm64 (1.7.2-3.1build2) ...
Selecting previously unselected package libaprutil1t64:arm64.
Preparing to unpack .../1-libaprutil1t64_1.6.3-1.1ubuntu7_arm64.deb ...
Unpacking libaprutil1t64:arm64 (1.6.3-1.1ubuntu7) ...
Selecting previously unselected package libaprutil1-dbd-sqlite3:arm64.
Preparing to unpack .../2-libaprutil1-dbd-sqlite3_1.6.3-1.1ubuntu7_arm64.deb ...
Unpacking libaprutil1-dbd-sqlite3:arm64 (1.6.3-1.1ubuntu7) ...
Selecting previously unselected package libaprutil1-ldap:arm64.
Preparing to unpack .../3-libaprutil1-ldap_1.6.3-1.1ubuntu7_arm64.deb ...
Unpacking libaprutil1-ldap:arm64 (1.6.3-1.1ubuntu7) ...
Selecting previously unselected package liblua5.4-0:arm64.
Preparing to unpack .../4-liblua5.4-0_5.4.6-3build2_arm64.deb ...
Unpacking liblua5.4-0:arm64 (5.4.6-3build2) ...
Selecting previously unselected package apache2-bin.
Preparing to unpack .../5-apache2-bin_2.4.58-1ubuntu8.4_arm64.deb ...
Unpacking apache2-bin (2.4.58-1ubuntu8.4) ...
Selecting previously unselected package apache2-data.
Preparing to unpack .../6-apache2-data_2.4.58-1ubuntu8.4_all.deb ...
Unpacking apache2-data (2.4.58-1ubuntu8.4) ...
Selecting previously unselected package apache2-utils.
Preparing to unpack .../7-apache2-utils_2.4.58-1ubuntu8.4_arm64.deb ...
Unpacking apache2-utils (2.4.58-1ubuntu8.4) ...
Selecting previously unselected package apache2.
Preparing to unpack .../8-apache2_2.4.58-1ubuntu8.4_arm64.deb ...
Unpacking apache2 (2.4.58-1ubuntu8.4) ...
Selecting previously unselected package ssl-cert.
Preparing to unpack .../9-ssl-cert_1.1.2ubuntu1_all.deb ...
Unpacking ssl-cert (1.1.2ubuntu1) ...
Setting up ssl-cert (1.1.2ubuntu1) ...
Setting up libapr1t64:arm64 (1.7.2-3.1build2) ...
Setting up liblua5.4-0:arm64 (5.4.6-3build2) ...
Setting up apache2-data (2.4.58-1ubuntu8.4) ...
Setting up libaprutil1t64:arm64 (1.6.3-1.1ubuntu7) ...
Setting up libaprutil1-ldap:arm64 (1.6.3-1.1ubuntu7) ...
Setting up libaprutil1-dbd-sqlite3:arm64 (1.6.3-1.1ubuntu7) ...
Setting up apache2-utils (2.4.58-1ubuntu8.4) ...
Setting up apache2-bin (2.4.58-1ubuntu8.4) ...
Setting up apache2 (2.4.58-1ubuntu8.4) ...
Enabling module mpm_event.
Enabling module authz_core.
Enabling module authz_host.
Enabling module authn_core.
Enabling module auth_basic.
Enabling module access_compat.
Enabling module authn_file.
Enabling module authz_user.
Enabling module alias.
Enabling module dir.
Enabling module autoindex.
Enabling module env.
Enabling module mime.
Enabling module negotiation.
Enabling module setenvif.
Enabling module filter.
Enabling module deflate.
Enabling module status.
Enabling module reqtimeout.
Enabling conf charset.
Enabling conf localized-error-pages.
Enabling conf other-vhosts-access-log.
Enabling conf security.
Enabling conf serve-cgi-bin.
Enabling site 000-default.
Created symlink /etc/systemd/system/multi-user.target.wants/apache2.service → /usr/lib/systemd/system/apache2.service.
Created symlink /etc/systemd/system/multi-user.target.wants/apache-htcacheclean.service → /usr/lib/systemd/system/apache-htcacheclean.service.
Processing triggers for ufw (0.36.2-6) ...
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.2) ...
Scanning processes...
Scanning linux images...

Running kernel seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

## enable & start apache2
root@node1:~# systemctl enable apache2
Synchronizing state of apache2.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable apache2
root@node1:~# systemctl restart apache2

root@node1:~# systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled)
     Active: active (running) since Sun 2024-08-11 22:33:51 HKT; 8s ago
       Docs: https://httpd.apache.org/docs/2.4/
    Process: 12732 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
   Main PID: 12736 (apache2)
      Tasks: 55 (limit: 4550)
     Memory: 5.0M (peak: 5.4M)
        CPU: 10ms
     CGroup: /system.slice/apache2.service
             ├─12736 /usr/sbin/apache2 -k start
             ├─12738 /usr/sbin/apache2 -k start
             └─12739 /usr/sbin/apache2 -k start

Aug 11 22:33:51 node1 systemd[1]: Starting apache2.service - The Apache HTTP Server...
Aug 11 22:33:51 node1 apachectl[12735]: AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 192.168.70.5. Set the 'ServerName' directive globally to suppress this message
Aug 11 22:33:51 node1 systemd[1]: Started apache2.service - The Apache HTTP Server.

root@node1:~# netstat -luntp | grep -i 80
tcp6       0      0 :::80                   :::*                    LISTEN      12736/apache2
udp6       0      0 fe80::20c:29ff:fee6:123 :::*                                2011/ntpd

  • Create deploy user and grant privileges on node1
## run on node1 server
## create appusr to deploy pkg
root@node1:~# useradd appusr

root@node1:~# mkdir /home/appusr

root@node1:~# chown -R appusr:appusr /home/appusr/

root@node1:~# passwd appusr
New password:
Retype new password:
passwd: password updated successfully

## grant permission on /var/www/html
root@node1:~# setfacl -R -m u:appusr:rwx /var/www/html

## evaluate the permission
root@node1:~# getfacl /var/www/html
getfacl: Removing leading '/' from absolute path names
# file: var/www/html
# owner: root
# group: root
user::rwx
user:appusr:rwx
group::r-x
mask::rwx
other::r-x

  • Copy ssh public key from gitlab-runner@cicd to appusr@node1
## run on cicd server
## copy gitlab-runner ssh public key to appusr@node1
gitlab-runner@cicd:~$ ssh-copy-id -i ~/.ssh/id_ed25519.pub appusr@192.168.70.5
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/gitlab-runner/.ssh/id_ed25519.pub"
The authenticity of host '192.168.70.5 (192.168.70.5)' can't be established.
ED25519 key fingerprint is SHA256:V41H7BRPUlw1DhShjXxDT9Dr7WflEwsE0ySUXKe0joU.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
appusr@192.168.70.5's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'appusr@192.168.70.5'"
and check to make sure that only the key(s) you wanted were added.

## evaluate can login without passwd
gitlab-runner@cicd:~$ ssh appusr@192.168.70.5
Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-40-generic aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun Aug 11 10:42:54 PM HKT 2024

  System load:  0.0               Temperature:             11758.9 C
  Usage of /:   4.0% of 68.30GB   Processes:               217
  Memory usage: 6%                Users logged in:         1
  Swap usage:   0%                IPv4 address for ens160: 192.168.70.5


Expanded Security Maintenance for Applications is not enabled.

4 updates can be applied immediately.
To see these additional updates run: apt list --upgradable

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


$ exit
Connection to 192.168.70.5 closed.

  • Clone code via gitlab-runner@cicd and submit a new version of index.html.
## run on cicd server
## create a project directory and grant privilege to gitlab-runner
➜  ~ mkdir /develop/gitlab
➜  ~ chown -R gitlab-runner:gitlab-runner /develop/gitlab
➜  ~ su - gitlab-runner
gitlab-runner@cicd:~$ cd /develop/gitlab/

## clone webpage code(can find the link on project page)
gitlab-runner@cicd:/develop/gitlab$ git clone git@192.168.70.6:root/webpage.git
Cloning into 'webpage'...
The authenticity of host '192.168.70.6 (192.168.70.6)' can't be established.
ED25519 key fingerprint is SHA256:V41H7BRPUlw1DhShjXxDT9Dr7WflEwsE0ySUXKe0joU.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:1: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.70.6' (ED25519) to the list of known hosts.
remote: Enumerating objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3 (from 1)
Receiving objects: 100% (3/3), done.

## create and submit a new index.html to deploy
gitlab-runner@cicd:/develop/gitlab$ cd webpage/
gitlab-runner@cicd:/develop/gitlab/webpage$ vim index.html
gitlab-runner@cicd:/develop/gitlab/webpage$ cat index.html
Gitlab CICD test
gitlab-runner@cicd:/develop/gitlab/webpage$ git add *
gitlab-runner@cicd:/develop/gitlab/webpage$ git commit -am '1st commit'
[main e2b7edd] 1st commit
 1 file changed, 1 insertion(+)
 create mode 100644 index.html
gitlab-runner@cicd:/develop/gitlab/webpage$ git push -u origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 332 bytes | 332.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To 192.168.70.6:root/webpage.git
   cb3c9f8..e2b7edd  main -> main
branch 'main' set up to track 'origin/main'.

Let’s do it!

  • Configure pipeline.
  • Add deploy script. In this sample, will get the latest version of webpage, and copy it to node1:/var/www/html. Can refer to below script. After confirm the script here, please click ‘Commit Change’ for next.
# This file is a template, and might need editing before it works on your project.
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
#
# You can copy and paste this template into a new `.gitlab-ci.yml` file.
# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword.
#
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml

stages:          # List of stages for jobs, and their order of execution
  - deploy

deploy-job:      # This job runs in the deploy stage.
  stage: deploy  # It only runs when *both* jobs in the test stage complete successfully.
  environment: production
  script:
    - hostname
    - cd /develop/gitlab/webpage
    - git pull
    - scp index.html appusr@192.168.70.5:/var/www/html

  • Can find the job run successful on Jobs Tab.

Evaluate the deployment

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *