Self-hosted GitLab using Docker

GitLab is providing its community edition as a Docker image on Docker Hub. Furthermore, they provide a comprehensive documentation of how to install and configure this image. That’s why I won’t loose words about the basic installation.

The only thing I want to describe in this article is how I made my private GitLab instance available via an encrypted HTTPS connection provided by Traefik. For this, knowing the idea of a reverse proxy is helpful, especially Traefik and its integration with Docker. Oh look, there is an article about this.

By default, GitLab’s Docker container starts an nginx web server that is processing all web requests. This can be both HTTP on port 80 and HTTPS on port 443. But in my setup, Traefik is processing the web requests on those ports. So the incoming requests are being forwarded from Traefik to the running Gitlab Docker container. Internally, Traefik is forwarding them using HTTP, which will lead to some problems regarding GitLab’s configuration.

Because for GitLab incoming requests are HTTP requests, it needs to be configured in a way, so that it is still possible to reach repositories via HTTPS. Otherwise, I would have HTTP content within an HTTPS site, which is undesired mixed content. To tackle this problem, some additional configuration values in docker-compose.yml are necessary.

So here is my modified docker-compose.yml:

version: "3"

networks:
  proxy:
    external: true
  internal:
    external: false

services:
  web:
    image: 'gitlab/gitlab-ce:latest'
    restart: always
    hostname: 'gitlab.domain.net'
    environment:
    GITLAB_OMNIBUS_CONFIG: |
      external_url 'https://gitlab.domain.net'
      gitlab_rails['smtp_enable'] = true
      # some smtp settings...
      nginx['listen_port'] = 80
      nginx['listen_https'] = false
      nginx['proxy_set_headers'] = {
        "X-Forwarded-Proto" => "https",
        "X-Forwarded-Ssl" => "on"
      }
    ports:
      - '2222:22'
    volumes:
      - '/path/to/gitlab/config:/etc/gitlab'
      - '/path/to/gitlab/logs:/var/log/gitlab'
      - '/path/to/gitlab/data:/var/opt/gitlab'
    labels:
      - traefik.backend=gitlab
      - traefik.frontend.rule=Host:gitlab.domain.net
      - traefik.docker.network=proxy
      - traefik.port=80
    networks:
      - internal
      - proxy

The important changes are highlighted on line 19 to 24. I configured GitLab’s nginx to only listen on port 80 on which incoming requests are forwarded from Traefik. Using this configuration, it is possible to access GitLab using an HTTPS connection and SSH.

Furthermore, SSH connections on port 22 (container) are forwarded from port 2222 (host). This is necessary, because port 22 is already used by the SSH daemon on the host machine. But now, some additional configuration is necessary when connecting via SSH. In my local ~/.ssh/config, I added the following lines:

Host gitlab.domain.net
HostName gitlab.domain.net
Port 2222

This defines to use port 2222 when connecting to gitlab.domain.net via SSH.

Summary

Running a private GitLab instance in Docker is quite easy, mostly because GitLab is proving all necessary parts (documentation, Docker images, …). But since all my Docker containers are running behind Traefik, some additional configuration is necessary. On the one hand, a solution to handle internal HTTP requests from Traefik to GitLab while still avoiding HTTP/HTTPS mixed content warnings in the browser. On the other hand, using a different port for SSH connections, when cloning repositories via SSH.

Leave a Reply

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