Gitlab CE Behind Traefik

At my university's CS department, we are trying to set up an internal GitLab
CE instance for CI/CD of our projects. Based on our infrastructure, I decided to
manage a Traefik instance and deploy GitLab Omnibus on Docker.

Nginx #

To have Traefik reverse-proxy the nginx instance, simply disable HTTPS and route
the traffic to container port 80:

nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['real_ip_trusted_addresses'] = [ '' ] # Traefik's internal addresss
nginx['real_ip_header'] = 'X-Real-Ip' # X-Real-Ip is set by Traefik
nginx['real_ip_recursive'] = 'on'

container labels: "80"
traefik.http.routers.gitlab.service: "gitlab"
traefik.http.routers.gitlab.entrypoints: "web"
traefik.http.routers.gitlab.rule: "Host(``)"
traefik.http.routers.gitlab.tls.certResolver: "http"

Grafana #

GitLab Omnibus has a built-in Grafana instance that authenticates user using
GitLab OAuth. I ran into the issue where Grafana was not able to complete the
OAuth process. Let's say the machine's public facing address is and
Traefik container IP address is I looked into the logs and
found this in /var/log/gitlab/grafana/current:

2021-04-19_18:15:05.40382 t=2021-04-19T18:15:05+0000 lvl=eror msg=login.OAuthLogin(NewTransportWithCode) logger=context userId=0 orgId=0 uname= error="Post \"\": dial tcp connect: connection timed out"

Apparently the GitLab container is not able to connect to
via Double checking on a shell session inside the container confirms
the case:

root@server:/srv/gitlab-ce# docker exec -it gitlab-ce_web_1 bash
root@96c275d00c01:/# curl -v
* Trying

It turns out ufw was blocking the traffic from all Docker network interfaces
to the host machine (INPUT chain). I decided to disable ufw once and for all.

It is worth to mention that in GitLab's official documentation on running with
Docker Compose, they suggest specifying hostname option for the GitLab container.
Actually, the option should not be used, because that would resolve to inside the container.

At the beginning, you need access to the Grafana admin account to grant
administrative permissions to other accounts (i.e. your Grafana account). To do
that, first enable the login form, specify a secure password and log in.

grafana['disable_login_form'] = false
grafana['admin_password'] = 'foobar'

After you've done the administrative actions, do not forget to turn it back off:

grafana['disable_login_form'] = true

GitLab Pages #

In some of our CI pipelines, there are static websites built by Vue.js that we
wish to be directly accessable in Jobs Artifacts, and that is handled by GitLab
Pages daemon. To make it work with Traefik, disable pages_nginx and have
Traefik route the requests to the Pages daemon directly:

pages_external_url ""
pages_nginx['enable'] = false
gitlab_pages['external_http'] = ['']

Traefik labels: "8081"
traefik.http.routers.gitlab-pages.service: "gitlab-pages"
traefik.http.routers.gitlab-pages.entrypoints: "web"
traefik.http.routers.gitlab-pages.rule: "Host(``) || Host(``) || HostRegexp(`{subdomain:[a-z]+}`)"
traefik.http.routers.gitlab-pages.tls.certResolver: "http"

Don't forget to expose port 8081 to make it reachable by Traefik.

In addition, our project visibility is set to internal.
According to the docs,
we needed to enable Access Control for GitLab Pages in gitlab.rb:

gitlab_pages['access_control'] = true

While the GitLab instance runs as a container, we also needed inplace_chroot:

gitlab_pages['inplace_chroot'] = true

It turned out that these two has conflicts
to each other, which is explained in this official documentation.

The workaround was pretty much a hack. While the GitLab instance is for
internal-only, I decided to go for the hack. Get a shell to the container,
and run:

mkdir -p /var/opt/gitlab/gitlab-rails/shared/pages/etc/
cp /etc/resolv.conf /var/opt/gitlab/gitlab-rails/shared/pages/etc/
cp -rv /etc/ssl /var/opt/gitlab/gitlab-rails/shared/pages/etc/
gitlab-ctl restart gitlab-pages

After setting this up, I found out that Pages only serves .html, .htm, .txt, and
. It does not serve .js or some images. So it ended up
no use for us.

Git SSH #

In our setup, we have Traefik inside of an another Docker network named traefik.
In the beginning, when I was trying to publish port 22 for git server, I forgot
to add the GitLab container in the default network as well. So don't forget to
do that if you're using similar setup.