How to Install GitLab with Docker on Ubuntu 22.04

Gitlab Server is an open-source version of the cloud-hosted Gitlab version control. The advantage of self-hosting your repositories over cloud hosting is the total control over your code.

This guide will teach you how to install Gitlab Server using Docker on a Ubuntu 22.04 server. Gitlab server offers two editions - the free Community edition and the paid Enterprise edition. We will be installing the Community edition. If you want more features, you can upgrade it to the Enterprise edition easily.

Prerequisites

  • A server running Ubuntu 22.04.

  • A non-root user with sudo privileges.

  • Uncomplicated Firewall(UFW) is enabled and running.

  • A Fully Qualified domain name (FQDN) pointing to the server like, gitlab.example.com.

  • Everything is updated.

    $ sudo apt update && sudo apt upgrade
    

Step 1 - Configure Firewall

The first step before installing any packages is to configure the firewall to allow HTTP and HTTPS connections.

Check the status of the firewall.

$ sudo ufw status

You should see something like the following.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Allow HTTP and HTTPs ports.

$ sudo ufw allow http
$ sudo ufw allow https

Open port 587 for receiving mails via SMTP. You may be using a different port with your SMTP mailer.

$ sudo ufw allow http
$ sudo ufw allow 587

Check the status again to confirm.

$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
587                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
587 (v6)                   ALLOW       Anywhere (v6)

Step 2 - Install Dependencies

Before installing Gitlab, we need to install certain packages that will be required during the course of our tutorial.

$ sudo apt install ca-certificates curl openssh-server apt-transport-https gnupg lsb-release -y

Some of these packages may be pre-installed on your system.

Step 3 - Change System's SSH port

Gitlab uses the default SSH port which will conflict with the system's SSH port. For best results, it's better to change the system's default port.

To do this, open the /etc/ssh/sshd_config file for editing.

$ sudo nano /etc/ssh/sshd_config

Find the following line, remove the hash(#) in front of it and change the value from 22 to anything else of your choice. For our tutorial, we have picked 2425 by changing

#Port 22

to

 Port 2425

Save the file by pressing Ctrl + X and entering Y when prompted.

Restart the SSH service.

$ sudo systemctl restart sshd

Open port 2425 in the firewall.

$ sudo ufw allow 2425

Close your current SSH session and re-login using the new port.

$ ssh username@<serverIP> -p 2425

Step 4 - Install Docker and Docker Compose

Add Docker's official GPG key.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg

Run the following command to add the Docker repository.

$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Update the system to include Docker's repository.

$ sudo apt update

Install Docker.

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

This tutorial will be using the Docker Compose v2 plugin instead of the older legacy binary. Therefore, the command for running it has changed from docker-compose to docker compose and this is reflected here.

Docker runs with elevated privileges so you will need to use sudo frequently to run commands. The better option is to add your Linux user account to the docker user group.

$ sudo usermod -aG docker ${USER}

The ${USER} variable picks up the currently logged-in system account. If you are not logged in with the user you want to give privileges to, replace ${USER} with the username.

To apply for the new group membership, log out of the server and back in, or use the following command. You will be prompted for the user's password.

$ su - $(USER)

Step 5 - Set up Docker Volumes

Before proceeding with the installation, we need to set the location for Gitlab data and configuration to be accessed via Docker volumes.

Create the Docker volume directory.

$ sudo mkdir /srv/gitlab -p

Create a directory for the Docker compose file.

$ mkdir ~/gitlab-docker

Switch to the directory.

$ cd ~/gitlab-docker

Create an environment variable file and open it for editing.

$ nano .env

Paste the following code to define the $GITLAB_HOME variable.

GITLAB_HOME=/srv/gitlab

The Gitlab container uses host-mounted volumes to store persistent data. The following table shows the mapping of the local location of the Gitlab directories to the location of containers and their respective usage.

Local Location Container Location Usage
$GITLAB_HOME/data /var/opt/gitlab For storing application data.
$GITLAB_HOME/logs /var/log/gitlab For storing logs.
$GITLAB_HOME/config /etc/gitlab For storing Gitlab configuration.

Step 6 - Install Gitlab using Docker Compose

Make sure you are inside the Docker compose directory of Gitlab.

Create and open the Docker compose configuration file for editing.

$ nano docker-compose.yml

Paste the following code in it.

version: '3.6'
services:
  web:
    image: 'gitlab/gitlab-ee:latest'
    container_name: 'gitlab-howtoforge'
    restart: always
    hostname: 'gitlab.example.com'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'https://gitlab.example.com'
        gitlab_rails['smtp_enable'] = true
        gitlab_rails['smtp_address'] = "email-smtp.us-west-2.amazonaws.com"
        gitlab_rails['smtp_user_name'] = "SESUsername"
        gitlab_rails['smtp_password'] = "SESKey"
        gitlab_rails['smtp_domain'] = "example.com"
        gitlab_rails['smtp_enable_starttls_auto'] = true
        gitlab_rails['smtp_port'] = 587
        gitlab_rails['smtp_authentication'] = "login"
        gitlab_rails['gitlab_email_from'] = '[email protected]'
        gitlab_rails['gitlab_email_reply_to'] = '[email protected]'
        # Add any other gitlab.rb configuration here, each on its own line
    ports:
      - '80:80'
      - '443:443'
      - '22:22'
      - '587:587'
    volumes:
      - '$GITLAB_HOME/config:/etc/gitlab'
      - '$GITLAB_HOME/logs:/var/log/gitlab'
      - '$GITLAB_HOME/data:/var/opt/gitlab'
    shm_size: '256m'

Let us take a look at all the options defined in the file.

  • image refers to the location of the Docker image of Gitlab on Dockerhub.
  • container_name allows you to apply a label to your docker container, for use when referencing the container within a Docker network.
  • restart specifies a restart policy for the container. Setting it to always means that a container if exited, will automatically get restarted.
  • hostname defines the container's internal hostname or in this case, the URL where your Gitlab will be installed.
  • environment supplies the variable GITLAB_OMNIBUS_CONFIG which allows you to enter any Gitlab configuration setting.
  • external_url refers to the domain where your Gitlab will be installed. Using https protocol ensures automatic installation of the Let's Encrypt SSL certificate.
  • SMTP details - we have included SMTP details so that the Gitlab instance can send important emails and notifications. For our tutorial, we are using Amazon's SES service. You can however use any service of your choice. Check the Gitlab documentation for SMTP mailers to learn how to configure them.
  • ports tell the container to publish ports or a range of ports to the host. Since Gitlab needs ports 22(SSH), 80(HTTP), 443(HTTPS), and 587(SMTP), they have been exposed to the system. If you want Gitlab to use a non-standard port on your server (probably because it's not available), you would provide the host port first and then the container port. For eg, since your server is already using SSH(22) port, you can tell Gitlab to use SSH via a different port, say 3333. Then you would change 22:22 in the above file to 3333:22. You will also need to add the line gitlab_rails['gitlab_shell_ssh_port'] = 3333 under GITLAB_OMNIBUS_CONFIG above.
  • volume defines the directories present on the server to store persistent data. As defined in step 5, $GITLAB_HOME can now be used in the compose file to mount relevant directories on the container.
  • shm_size refers to the shared memory used by the container. By default, Docker allocates 64MB to the shared memory directory (mounted at /dev/shm). This can prove insufficient for the Prometheus metrics that the Gitlab container generates. Therefore, a minimum of 256MB of shared memory ensures the smooth running of the docker. You can increase its value depending upon the RAM your system has. Alternatively, you can disable Prometheus metrics from the admin area after installation. We will explore this in the next step.

Start the Gitlab Docker container.

$ docker compose up -d

It will take a few minutes for the process to finish. You can follow the progress using the Docker logs.

$ docker logs gitlab-howtoforge -f

Press Ctrl + C to exit the monitoring of the log.

You can check the status of the Gitlab container using the following command.

$ docker ps

Starting with Gitlab 14.0, it automatically generates a root password and stores it in the initiall_root_password file. This file can be found in the /srv/gitlab/config directory. Run the following command to view the root password.

$ sudo cat /srv/gitlab/config/initial_root_password

You will receive a similar output.

# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: Hz3t7Etn18wB6VAfBWyDlYbN2VQdMCO0xIIENfDHcFo=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.

Copy the password and save it for later use. Now that everything is set up, we can proceed with the configuration.

Step 7 - Configure Gitlab

Accessing Gitlab

Open the URL https://gitlab.example.com in your browser and you will get the following login screen.

Gitlab EE Login Screen

Enter root as the username and the password, you got in the previous step to sign in to your Gitlab dashboard. On signing in, you will be taken to the following dashboard screen.

Gitlab Dashboard

As you can see, Gitlab has already created a project to monitor the instance.

Restrict Public Sign-ups

By default, anyone can create an account and gain access. If you don't want it, you can turn it off. Fortunately, the setting for it is shown in the form of a pop-up screen on the dashboard. Click the Turn off button to restrict public sign-ups on your Gitlab instance. Doing so will redirect you to the following settings page.

Gitlab Sign-up restrictions

Uncheck the option Sign-up enabled to restrict them. Press the button Save changes to apply the setting.

In case, you don't see the pop-up in your dashboard, you can access the settings page by clicking the Menu button and accessing the Admin panel from there.

Gitlab Admin Menu

Once inside the admin panel, hover your mouse over the Settings option in the left sidebar and click on the General sub-menu. From there you can reach the Sign-up restrictions panel.

Gitlab General Admin Settings

Configure Gitlab Profile

Your default profile is pretty much bland and doesn't have anything to show for it. To change that, click on the user icon in the upper left-hand corner to bring up the drop-down menu and select the Edit profile option.

Gitlab Edit Profile button

You will be taken to the Profile settings page where you can add your name, e-mail, and other information about yourself. Click Update profile settings when you are done. Don't go back to the homepage as we have some more things to configure here.

Gitlab Edit Profile Page

Change Root Password

This is one of the most important steps. You should change your default root password immediately. With earlier versions, Gitlab required you to change it as part of the installation but now it has made it optional. To change your password, click on the Password menu from the left sidebar.

Gitlab Password Change Screen

Enter your password details and click Save password to make the change. You will be logged out of your instance and will have to log in again.

Change User name

You can change your default Gitlab username from root to anything of your choice. To do that, click the Account menu from the left sidebar.

Gitlab Account Username change page

Once on the page, enter your new username and click the Update username button to make the change. You will be prompted again for confirmation. Press the Update username button again to confirm the change.

You should also enable two-factor authentication here to improve your account security.

Disable Prometheus Metrics and improve Privacy

In the previous step, we discussed increasing the shared memory size for the droplet and to keep it at a minimum of 256 MB. It is required mainly to store the Prometheus metrics-related data on the disk. If you are not using the feature, you should disable the feature. You can do it only post-installation. To disable it, open the Admin Panel from the menu bar.

Once inside the Admin panel, open the Settings >> Metrics and profiling menu op