How to set up on-prem Gitlab VCS, Gitlab CI/CD, Gitlab Runner, with Docker
Tags: webdev, devops, tutorial, docker
Published: 2023-11-15 03:09:05

# Introduction
Hello! I haven't posted to Dev.to in a while. I have been learning more about Devops, Devsecops, and how I want to navigate my cybersecurity career.

I did some hands-on CI/CD by setting up my own pipeline in my local hosted Virtual Machines. This is sort of my documentation of what I did, a tutorial for others, but more importantly to guide my future self should I want to build something like this again.

To preface, I am a cybersecurity student from Singapore. Apart from school projects, internships, and a couple of side hustles, I do not have true web development/ system adminstration experience in a real-world, large scale production environment. My information may not be 100% accurate; I may be deviating from best practices. Nevertheless, I know that it works. I couldn't find information on this specific permutation of Gitlab and Docker so I hope my sharing would be useful for others who want to build something similar. Let me know if there's anything I could have done better!

# Infrastructure

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xy77qrs3mw3whflixwqj.jpg)

The infrastructure is actually very simple. It's just 2 docker containers running inside an ubuntu VM. You could even run the 2 docker containers inside Windows. Just need to configure slightly differently. The containers are even pulled from Dockerhub. What made this difficult for me was the configuration files. There's small details that I had to dig from several sources to get my pipeline working.

# Prerequisites
If running in a VM, you might want to allocate more resources. My Gitlab was quite laggy. I suspect its hardware ... If your Gitlab starts becoming unresponsive, just restart the machine. Avoid pausing the VM too.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pce4loo0y5wlzkowz2j1.png)

Apart from that, you just need Docker.

It's very simple with apt on Ubuntu. Steps [here](https://docs.docker.com/engine/install/ubuntu/)

You could also use Docker Desktop for a GUI process however most guides and documentation online give steps through CLI so I used CLI too.

After installing Docker, you might realise that most Docker commands require sudo. If you do not want to keep typing in sudo:
```
sudo usermod -aG docker $USER
```
**HOWEVER** this opens up a [privilege escalation security vulneraibility](https://fosterelli.co/privilege-escalation-via-docker.html). This entire write up is for home testing and learning. This is **NOT** for production.

That's all! On to the actual installation of Gitlab!

# Installation
Gitlab has a CE and EE version (community and enterprise). Both are free to download. I used the EE version. Download the Gitlab EE image from Dockerhub
```
docker pull gitlab/gitlab-ee
```
In a Gitlab CI/CD pipeline, there are jobs. Different machines can run the jobs in whatever permutation needed for load balancing and scaling. I'm not very clear on this feature of Gitlab CI/CD but I know that to run a job you need a runner. As quoted in Runner [documentation](https://docs.gitlab.com/runner/install/index.html), 
> For security and performance reasons, you should install GitLab Runner on a machine that is separate to the machine that hosts your GitLab instance

I'm not too sure about the specifics, but I just wanted a single runner to run a simple pipeline. Based on this [thread](https://forum.gitlab.com/t/register-multiple-runners-on-same-host/38650/7), it seems okay for my use case to run both the Gitlab container and the Runner container on the same machine.

So that's what I did.
```
docker pull gitlab/gitlab-runner
```

# Configuration
Now this is the part where I couldn't find a single source of answers. 

From Gitlab [documentation](https://docs.gitlab.com/ee/install/docker.html), first create a directory for the Gitlab files:
```
export GITLAB_HOME=/srv/gitlab
```
Then create a file named `docker-compose.yml` (actually you can name it anything you want but this step makes some processes more convenient). Docker compose files allow you to write whatever configuration you want before running the container. Multiple containers can be run with one single compose file too. But I'm not too sure about the best practices of this. I believe IAC tools such as Ansible can be used too but for my testing I just used one compose file for one container.

Gitlab container's `docker-compose.yml`
```yml
version: '3.6'
services:
	docker:
		volumes:
		    - '/var/run/docker.sock:/var/run/docker.sock'
		tty: true
		stdin_open: true
		image: docker
	web:
		image: 'gitlab/gitlab-ee:latest'
		restart: always
		environment:
			GITLAB_OMNIBUS_CONFIG: |
				
		ports:
			- '80:80'
			- '443:443'
			- '22:22'
			- '8093:8093'
		volumes:
			- '$GITLAB_HOME/config:/etc/gitlab'
			- '$GITLAB_HOME/logs:/var/log/gitlab'
			- '$GITLAB_HOME/data:/var/opt/gitlab'
		shm_size: '256m'
```
I don't remember exactly what each config is for but I can roughly explain a few key ones:
`volumes` this is to make storage persistent
`restart` I think this is to run the container on boot
`ports` apart from the common ports, I believe port 8093 is for [session_server](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-session_server-section).
`shm_size` the Gitlab app is very resource heavy so apparently this increases RAM allocation... I think

Next, in a separate directory, create another `docker-compose.yml`
```yml
version: '3.6'
services:
	 gitlab-runner:
		  container_name: gitlab-runner
		  restart: always
		  stdin_open: true
		  tty: true
		  command: register
		  volumes:
				- '/srv/gitlab-runner/config:/etc/gitlab-runner'
				- '/var/run/docker.sock:/var/run/docker.sock'
		  image: 'gitlab/gitlab-runner:latest'
		  ports:
				- '81:80'
				- '8094:8093'
```

Then in the Gitlab container directory and the Runner directory:
```
docker compose up -d
```

Gitlab takes some time to start. To see the status of the containers:
```
docker ps
```

Next, you need  to access the Gitlab app's config files. You could try open an editor within the container or do what I did lol. Install the docker extention in VS code.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pa227awiai6bad9qcgeo.png)
Navigate to `etc/gitlab/gitlb.rb` and look for the `external_url`. For home testing/learning you can use your own IP address. `hostname -I`. Read [here](https://stackoverflow.com/a/28005168)

If everything goes well, open your web browser and enter your IP address. You should see the Gitlab login. The default username should be `root` while the password can be found in `etc/gitlab/initial_root_password`. You can change the password through the web GUI afterwards. Once logged in, click click click ~ create your project.

Then there's 2 things you'd want to look at. First, the pipeline editor:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tkq62mbdrf0tpkddkhb8.png)
This is where you configure your CI/CD pipeline with whatever building and testing you want.

Second, you'd want to link your runner to your project.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rd58kb3jo46n1lgtip0f.png)

The Gitlab app guides you on the runner registration. Just click new runner registration and follow the steps. **Allow the runner to run untagged jobs**. This is just for convenience. Next screen shows you the steps to continue.

To run commands in the Runner app:
```
docker exec -it gitlab-runner bash
```

With that, you can start testing your CI/CD pipeline script! Perhaps try some devsecops tools. Snyk? Synopsys? 

Thank you for reading my post :) I am still learning so please let me know if I can do this better! I might just be spreading misinformation lol