GitLab CE - tips and tricks

Tags: #<Tag:0x00007f0caf090ed0> #<Tag:0x00007f0caf090d90> #<Tag:0x00007f0caf090c50> #<Tag:0x00007f0caf090b10> #<Tag:0x00007f0caf0909a8>


GitLab, Hub, Sub... same Git, different day


Use cases - my lab, my rules

If I want to post some personal files and projects to a private repository, cloud services aren’t my first choices. Sure, there are many. GitHub, BitBucket… Codeplex… what’s next?

My use cases include comitting various archives for Malware Analysis and Forensics. These projects remain private, but I also do not want that some AV deletes my work. Cloud hosters can just delete security-critical content, if they think that it poses risks to their customers and their service. Sometimes the ToS prohibit to commit Malware related content.

In order to keep a distance, I host my own GitLab CE server. It’s packed with features, freely available, and useful as a self-hosted service. And it’s in my lab, where I set the rules.

Here’re my tips and tricks.

Works for me - works for you

Here are some service config tricks.

GitLab CE behind an Apache Reverse Proxy

If you have a web-server, or two, as intermediates - as Reverse Proxies - you need to configure them appropriately. The GitLab documentation about is scattered, which is why I document my approach here:

  • I use an Apache2 ReverseProxy, but an Nginx or Lighttpd can do the same.
  • I have a GitLab VM guest, with an internal IP within That’s the default IP range of the internal dnsmasq, which works with libvirt on Debian.

Apache2 ReverseProxy with x-fer headers for GitLab CE

Here is what I put in the sites-enabled (Debian style config layout) for Apache2:

<VirtualHost *:80>

    ProxyPreserveHost On
    ProxyRequests Off
    ProxyPass /
    ProxyPassReverse /

    RequestHeader set X_FORWARDED_PROTO 'https'
    RequestHeader set X-Forwarded-Ssl on

    CustomLog /var/log/apache2/code_apache_proxy_https_access.log combined
    ErrorLog /var/log/apache2/code_apache_proxy_https_error.log

The Apache will listen on the external IP, and pass the HTTP requests along to the internal IP on port 80. It’s an intermediary as well. I have another service in front for the TLS handling.

I recommend that you take a look at Pound or HAProxy for this. Or let a free CDN service handle this, like I do for now. The point is to split the encryption handling into another layer.

In GitLab CE I needed to change the hostname to, to my FQDN to be precise. In the gitlab.rb this can look like this:

gitlab_rails['gitlab_hostname'] = ''
gitlab_rails['gitlab_ssh_host'] = ''

For the sake of completion I added this to the next section, where I list my config for this.

Result: you can run GitLab behind a Reverse Proxy. It’s supported and easy to do. For now it’s not well documented anywhere, but here I think.

Configure GitLab CE to respect a ReverseProxy

I put this into the respective gitlab.rb with is in /etc/gitlab on Debian:

external_url ''

nginx['listen_port'] = 80
nginx['listen_https'] = false

nginx['proxy_set_headers'] = {
   "X-Forwarded-Proto" => "https",
   "X-Forwarded-Ssl" => "on"

gitlab_rails['gitlab_hostname'] = ''
gitlab_rails['gitlab_ssh_host'] = ''    
  • Keep in mind: external_url is a function. Don’t use =. The URL string is a parameter.
  • I set the headers to reflect that there is https although at that layer of the app stack I use port 80 http clear-text
    This is important in order to have the GitLab project URLs with httpS://
    The internal VM and the intermediate web server(s) do not handle TLS / SSL. GitLab cannot detect that it’s behind multiple web servers in this setup.

Result: GitLab will display valid URLs for the project, which do not indicate that the functions are layered and that there is an app stack.