Introduction
GitLab is a popular self-hostable Git service. Thanks to GitLab, development teams can work with a better workflow, and more details are available on their official website.
This tutorial describes how to properly install a full-featured GitLab instance with initial configuration using Docker.
Prerequisites
- A fully updated Debian 11 server with at least 4GB of ram (8GB+ recommended)
- A non-root sudo user
- A working nginx server
GitLab does not work by default, and in any official way, on ARM64 machines as of Q2 2022. All RCS machines are x86-based and supported.
1. Install Docker and Compose
Note: If Docker (with Compose) is already installed in the system, this step can be avoided.
Download and Execute the Installer from Docker's Website
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
Install Compose
apt -y install docker-compose
Docker Auto-Start
The GitLab instance runs on Docker, if the docker service gets stopped for any reason, the GitLab instance will be stopped too. To prevent unexpected downtime, it is highly recommended to set Docker to start itself automatically when the system boots.
systemctl enable docker
Start Docker
Docker should be now running on the RCS Instance, it is possible to check its status with
service docker status
If Docker is not running, it needs to be manually started via
service docker start
2. Prepare Configuration
It is recommended to store the GitLab configuration in an appropriate directory, in this tutorial, the home folder of the user gitlab
is used.
adduser gitlab --disabled-login
cd /home/gitlab
Create a docker-compose file, and this allows future GitLab upgrades with the ease of a single command.
touch docker-compose.yml
Open the created file with the text editor of your choice (for example: nano
)
nano docker-compose.yml
The GitLab container configuration has to be set here. Note: This file follows the docker-compose specifications. More details are in the official documentation, in case further customization is required.
2.1 Recommended Configuration
version: '3.6'
services:
web:
image: 'gitlab/gitlab-ee:latest'
restart: always
environment:
GITLAB_OMNIBUS_CONFIG: |
external_url 'https://git.example.com'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "mail.example.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "git@example.com"
gitlab_rails['smtp_password'] = "PleaseUseASafePasswordAndNotThisOne"
gitlab_rails['smtp_domain'] = "example.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'git@example.com'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@example.com'
ports:
- '127.0.0.1:6100:443'
- '22:22'
volumes:
- './config:/etc/gitlab'
- './logs:/var/log/gitlab'
- './data:/var/opt/gitlab'
shm_size: '256m'
2.2 Configuration Explanation
image: 'gitlab/gitlab-ee:latest'
-> This configuration uses GitLab Enterprise Edition instead of Community Edition. If the Community Edition is preferred replacegitlab/gitlab-ee:latest
withgitlab/gitlab-ce:latest
.shm_size: '256m'
-> Defines the size of the/dev/shm
partition mounted on the container. Requires at least 256M to allow GitLab to work properly.
2.2.1 Omnibus Configuration
external_url 'https://git.example.com'
-> Replace git.example.com with the FQDN set in step 2.1. External URL defines at which URL the GitLab instance will be reached.gitlab_rails['smtp_*']
-> Configuration for the mailserver used to send notifications.gitlab_rails['gitlab_email_from']
-> The email used by the GitLab instance to send emails and notifications.gitlab_rails['gitlab_email_display_name']
-> The sender name forgitlab_email_from
used by the GitLab instance to send emails and notifications.gitlab_rails['gitlab_email_reply_to']
-> The email used as "reply-receiver" for GitLab notifications.gitlab_rails['gitlab_root_password']
-> Unrecommended The password for the root account of the GitLab instance. In case this variable remains blank (which is highly recommended) GitLab is going to automatically generate a secure password that remains accessible for 24h after the setup.
2.2.2 Ports configuration
127.0.0.1:6100:443
-> HTTPS is not going to be used directly from GitLab. Secure access is handled directly by NGINX. The port 443 is forwarded just locally and so not available to the internet.22:22
-> SSH port is forwarded and available to the internet. This allows Git interactions with SSH rather than with HTTPS (which is a preferred method). If port 22 is used by the default SSH service of the server it is needed to use a different port; otherwise, the container is not able to start. Eventually, a different external port may be used (change the 22 before the colon to the port that will be used) for the container, but this requires further customization in GitLab settings to make explicit the port that is used by SSH.
2.2.3 Volumes
./config:/etc/gitlab
-> Mounts the GitLab configuration folder to./config
. This allows to store configuration data on the disk and prevents data loss if the container gets deleted or updated../logs:/var/log/gitlab
-> Mounts the GitLab logs folder to./logs
. It is highly recommended, but not mandatory, as logs are still available viadocker logs [containername]
until the container gets deleted or updated../data:/var/opt/gitlab
-> Mounts the GitLab data folder to./data
. This folder is really important, for that reason a whole section is dedicated to its explanation: seeGitLab Data Folder
.
3. GitLab Data Folder
This folder contains all the projects' data and is the most important folder to keep safe to prevent data loss. If this folder gets accidentally deleted or lost there is no way to recover what was hosted on the GitLab instance.
3.1 Recommended Solution
RCS provides a service called Block Storage (VBS) which ensures high access speed thanks to Enterprise-grade NVMe Drives, cost-effective scalability up to 10TB, high availability, data replication, and redundancy, representing the state-of-the-art method to keep GitLab data safe.
3.2 Preparing the Folder for VBS
If the recommended way of using RCS Block Storage is chosen, a tutorial on how to mount the VBS on the Debian server is available.
After mounting the VBS, execute the command below to link the ./data
folder to the VBS.
Note: This needs to be done before the GitLab container is started for the first time.
ln -s /mnt/VBSFolder ./data
4. Nginx Configuration
Nginx is hosted outside of the docker container and handles all the encryption and traffic forwarding.
Create an additional Nginx Virtual Host file in /etc/nginx/sites-available
.
touch /etc/nginx/sites-available/git.example.com
Open the created file with the text editor of your choice and paste the configuration below.
nano /etc/nginx/sites-available/git.example.com
server {
root /dev/null;
server_name git.example.com;
charset UTF-8;
proxy_intercept_errors on;
location / {
# allow 10.8.0.0/16;
# deny all;
recursive_error_pages on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass https://127.0.0.1:6100;
client_max_body_size 500M;
}
#SSL Config
listen 443 ssl;
ssl_certificate /etc/ssl/git.example.com.crt;
ssl_certificate_key /etc/ssl/git.example.com.key;
#LOGs Config
error_log /var/log/nginx/example.com/git/errors.log;
access_log /var/log/nginx/example.com/git/access.log;
}
Save and close the NGINX configuration file.
NGINX requires the enable Virtual Hosts to be in the sites-enabled
folder. To enable a Virtual Host, use the command below:
ln -s /etc/nginx/sites-available/git.example.com /etc/nginx/sites-enabled/git.example.com
4.1 Configuration Explanation
root /dev/null
-> All the traffic is forwarded to the GitLab instance, the root folder is set to/dev/null
for security reasons.server_name git.example.com
-> Replace git.example.com with the FQDN set in step 2.1. This represents the domain name used to connect to the GitLab instance.proxy_intercept_errors on
andrecursive_error_pages on;
-> Allow nginx to handle and intercept HTTP errors.allow 10.8.0.0/16
anddeny all
-> Restrict IPs that can access the GitLab instance. To enable this rule remove the comment (#
) and change the IP subnet according to technical requirements. This must also include IPs from eventual GitLab runners.proxy_set_header *
-> Pass some HTTP headers to the GitLab instance.proxy_pass https://127.0.0.1:6100
-> The URL where the GitLab instance is running. This needs to be equal to the port configuration in thedocker-compose.yml
file.client_max_body_size 500M
-> If HTTP uploads are allowed and preferred to SSH this parameter is needed to prevent NGINX from stopping the requests when uploading big projects.listen 443 ssl
-> Sets listening to HTTPS port.ssl_certificate /etc/ssl/git.example.com.crt
-> The path to the certificate public key file. It can be generated with OpenSSL (causes issues with GitLab runners), Let'sEncrypt, or can be downloaded from your SSL certificate provider (Es. Cloudflare Origin Certificate).ssl_certificate_key /etc/ssl/git.example.com.key
-> The path to the certificate private key file. Must be the associated private key ofssl_certificate
./var/log/nginx/example.com/git/errors.log
and/var/log/nginx/example.copm/git/access.log
-> The path for NGINX log files. The folder must exist, if it doesn't create it withmkdir -p /var/log/nginx/example.com/git/
.
5. GitLab Start and Initial Configuration
After completing all the steps the GitLab instance is ready to be started. To start the Docker container running GitLab use the command below:
cd /home/gitlab && docker-compose up -d
This command changes the directory to the configuration one and starts the container creation steps (downloading of resources and startup). The first GitLab startup may require some minutes to be ready, as it needs to set up all the database tables and build some internal components.
5.1 Check if GitLab is Running
Checking the CPU usage it is possible to understand when the instance is ready to be used. To confirm the complete GitLab functionality, run the command below and compare the results (changing the container name may be required)
$ docker exec gitlab_web_1 gitlab-ctl status
run: alertmanager: (pid 1875) 232s; run: log: (pid 1294) 794s
run: crond: (pid 1695) 235s; run: log: (pid 886) 905s
run: gitaly: (pid 1769) 235s; run: log: (pid 552) 970s
run: gitlab-exporter: (pid 1766) 235s; run: log: (pid 1203) 815s
run: gitlab-kas: (pid 1656) 238s; run: log: (pid 807) 956s
run: gitlab-workhorse: (pid 1667) 238s; run: log: (pid 953) 888s
run: grafana: (pid 1895) 232s; run: log: (pid 1629) 258s
run: logrotate: (pid 497) 983s; run: log: (pid 509) 980s
run: nginx: (pid 1012) 880s; run: log: (pid 965) 887s
run: postgres-exporter: (pid 1884) 232s; run: log: (pid 1328) 789s
run: postgresql: (pid 658) 965s; run: log: (pid 673) 962s
run: prometheus: (pid 1784) 234s; run: log: (pid 1264) 801s
run: puma: (pid 889) 902s; run: log: (pid 900) 899s
run: redis: (pid 514) 977s; run: log: (pid 526) 974s
run: redis-exporter: (pid 1768) 235s; run: log: (pid 1235) 807s
run: registry: (pid 1676) 237s; run: log: (pid 1001) 881s
run: sidekiq: (pid 1584) 280s; run: log: (pid 919) 892s
run: sshd: (pid 33) 998s; run: log: (pid 32) 998s
5.2 First Login
GitLab is now up and running at the FQDN specified in the configuration files. Accessing the FQDN using a web browser should return a login page.
For the first login, the root account is required. The password for the login depends on the configuration used:
- if the unrecommended
gitlab_rails['gitlab_root_password']
has been used the password is the one that has been set in thedocker-compose.yml
file. - if the recommended method has been used the password is stored in config/initialrootpassword. The password can be accessed using
cat /home/gitlab/config/initial_root_password | grep Password
5.3 First Configuration
Some general parameters should be edited after installing GitLab, below there are technical explanations about the settings that are recommended to be changed.
5.3.1 Account Registration
Settings URL: /admin/application_settings/general
The first one, which is also recommended by GitLab with a banner after the login with the root account, is to disable account registration.
Disabling account registration is a great thing for private Git instances, as this prevents unattended users from taking space on the instance.
If the team that will use the GitLab instance is dynamic, a domain allowlist for the emails to use is viable. In this way just the users with emails from whitelisted domains will be able to register and use GitLab.
To proceed with the registration limitations, navigate to the URL at the top of this section and expand the Sign-up restrictions section.
To disable all the registrations and allow just administrators to create new accounts, remove the flag from Sign-up enabled
and save.
To allow just registrations from domains fill in the "Allowed domains for sign-ups" with a line-by-line list of all the domains allowed.
5.3.2 Header and Footer Customization
Settings URL: /admin/application_settings/appearance
GitLab allows replacing the default navigation bar and favicon logo.
This permits to easily differentiate the GitLab instance from other instances and helps prevent human distractions.
To proceed with the change navigate to the URL at the top of the section and upload the new logo in the two forms, then scroll down and save.
5.3.3 Add an User
Settings URL: /admin/users/new
GitLab allows administrators to register new accounts directly from the administration panel.
When the user is added an email will be sent to the provided email address with a one-time link to set a password.
To proceed with an account creation, navigate to the URL at the top of the section and fill in the data requested.
If the user needs to have access to CI/CD shared runners, the flag "User is validated and can use free CI minutes on shared runners." must be set.
6. Updating GitLab
Thanks to the use of Docker, updating GitLab requires just a few commands.
Always remember to check for eventual breaking changes on the GitLab changelog page before updating.
To update, execute the commands below:
docker-compose pull
docker-compose up -d
Note: GitLab may need some minutes to be fully available after the update. Consider proceeding with updates when the instance is not being used.
7. Conclusions
GitLab is now correctly installed, and it's ready for production use thanks to the slightly modified configuration.