How to deploy Gitlab with gitlab-runners and own container registry behind traefik as reverse proxy

We show you how we deployed our self hosted gitlab instance on a virtual machine, added gitlab runners to execute out build pipelines and added a container registry all behind a traefik reverse proxy.


Requirements

Docker

We’re using docker swarm do deploy and scale our services.

Traefik

version: '3.8'

services:
  app:
    image: traefik:v2.9.6
    environment:
      - TZ=Europe/Zurich
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
      - target: 5000
        published: 5000
        mode: host

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./etc/traefik:/etc/traefik:ro
      - traefik__acme:/letsencrypt

volumes:
  traefik__acme:
    name: stack__traefik__acme

docker-compose.yml

General configuration for your docker instance. The following file etc/traefik/traefik.yml is injected to /etc/traefik/traefik.yml within your container.

global:
  checkNewVersion: true
  sendAnonymousUsage: false

api:
  dashboard: true

log:
  level: INFO
  format: json

accessLog:
  format: json

entryPoints:
  web:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: websecure

  websecure:
    address: ':443'

providers:
  docker:
    endpoint: 'unix:///var/run/docker.sock'
    exposedByDefault: false
    swarmMode: true

  file:
    directory: /etc/traefik
    watch: true

traefik:
  docker:
    network: web

certificatesresolvers:
  letsencrypt:
    acme:
      email: info@example.com
      storage: /letsencrypt/acme.json
      httpChallenge:
        entryPoint: web

etc/traefik/traefik.yml

The file etc/traefik/domains/me_squibble_cluster01_git.yml handles the http router and services for our two domains git.intern.squibble.me and registry.git.intern.squibble.me.

http:
  routers:
    me_squibble__cluster01__git:
      entryPoints:
        - websecure
      rule: 'Host(`git.intern.squibble.me`)'
      service: me_squibble__cluster01__git@file
      tls:
        certResolver: letsencrypt

    me_squibble__cluster01__git_registry:
      entryPoints:
        - websecure
      rule: 'Host(`registry.git.intern.squibble.me`)'
      service: me_squibble__cluster01__git_registry@file
      tls:
        certResolver: letsencrypt

  services:
    me_squibble__cluster01__git:
      loadBalancer:
        servers:
          - url: http://<GITLAB SERVER IP>

    me_squibble__cluster01__git_registry:
      loadBalancer:
        servers:
          - url: http://<GITLAB SERVER IP>:5000

etc/traefik/domains/me_squibble_cluster01_git.yml

Virtual Machine

We used a ubuntu 22.04 server installation with currently 4 cpu cores and 8 GB RAM. On this vm we’ll install gitlab and gitlab-runner.

We do export the port 9022 to this vm to the public internet so we’re able to use this port for regular git commands.

To be able to use docker as a gitlab runner executor we have to install docker on our virtual machine.

Gitlab

Installation
sudo apt update

sudo apt install tzdata curl ca-certificates openssh-server

gpg_key_url="https://packages.gitlab.com/gitlab/gitlab-ce/gpgkey"
curl -fsSL $gpg_key_url| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/gitlab.gpg

sudo tee /etc/apt/sources.list.d/gitlab_gitlab-ce.list<<EOF
deb https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ focal main
deb-src https://packages.gitlab.com/gitlab/gitlab-ce/ubuntu/ focal main
EOF

sudo apt update

sudo apt install gitlab-ce
Configuration
# General Configuration
#
external_url 'https://git.intern.squibble.me'

gitlab_rails['gitlab_shell_ssh_port'] = 9022


# Mail Server Configuration
#
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "<MAIL_SERVER__HOST>"
gitlab_rails['smtp_port'] = <MAIL_SERVER__PORT>
gitlab_rails['smtp_user_name'] = "<MAIL_SERVER__USERNAME>"
gitlab_rails['smtp_password'] = "<MAIL_SERVER__PASSWORD>"
gitlab_rails['smtp_domain'] = "<MAIL_SERVER__DOMAIN>"

# The following configuration are optional and maybe not required for
# your mailserver setup.
#
gitlab_rails['smtp_authentication'] = "plain"
gitlab_rails['smtp_enable_starttls_auto'] = false
gitlab_rails['smtp_openssl_verify_mode'] = 'none'

gitlab_rails['gitlab_email_from'] = 'git@squibble.me'
gitlab_rails['gitlab_email_display_name'] = 'Squibble Gitlab'


# Registry Configuration
#
registry_external_url 'https://registry.git.intern.squibble.me'

gitlab_rails['registry_enabled'] = true
registry['enable'] = true

# Enable registry listening on all ip addresses on port 5000
# so we're able to connect traefik to this server and port.
#
registry['registry_http_addr'] = "0.0.0.0:5000"


# nginx Configuration
#
nginx['listen_port'] = 80

# SSL is handled via traefik and letsencrypt
#
nginx['listen_https'] = false

nginx['proxy_set_headers'] = {
  "Host" => "$http_host_with_default",
  "X-Real-IP" => "$remote_addr",
  "X-Forwarded-For" => "$proxy_add_x_forwarded_for",
  "X-Forwarded-Proto" => "https",
  "X-Forwarded-Ssl" => "on"
}

nginx['http2_enabled'] = false

# Disable the nginx server for container registry
#
registry_nginx['enable'] = false

/etc/gitlab/gitlab.rb

After applying all those settings execute gitlab-ctl reconfigure to enable the new settings. gitlab-ce is now correct configured so we should be able to access it via traefik.

Gitlab Runner

Installation

We followed the installation instructions on the official documentation and successfully installed version 15.9.2.

Runner registration

After successfully installing the gitlab-runner cli tool we have to register our runners to the gitlab instance.

Therefore we have to access /admin/runners on our gitlab instance and click on “Register an instance runner” to open a dropdown and copy the required registration token.

Replace the GITLAB_INSTANCE_HOST and REGISTRATION_TOKEN placeholder in the following commands with your registration token. You can specify the available resources to your needs.

sudo gitlab-runner register \
	--url https://<GITLAB_INSTANCE_HOST> \
	--registration-token <REGISTRATION_TOKEN> \
	--name cluster01/cirunner01--mem4g \
	--limit 6 \
	--executor "docker" \
	--tag-list "docker,cluster01,mem4G" \
	--docker-image ubuntu:jammy \
	--docker-cpus "4" \
	--docker-memory-swap "5G" \
	--docker-memory "4G" \
	--docker-memory-reservation "512m"

After execution this command you should see a new entry with your runner and state online.

Congratulations: You successfully deployed your self hosted gitlab instance with custom gitlab runners and a self hosted docker registry.