Running Gitlab with "strong" SSL enabled


In the spirit of 30C3, here’s a little guide on enabling SSL in Gitlab, using a secure cipher setup that priorizes security over performance. This guide is based on the default nginx based Gitlab setup, but of course it basically works for every nginx based site, and probably, with a little brain work, for Apache and other HTTP deamons as well.

Generating your certificate

In order to setup SSL, you first need a certificate. I’ve used a self-signed certificate for this purpose, which will show up as “not trusted” in your browser 1. Generating the certificate works as follows on a Linux machine with OpenSSL installed (which should be, if you’re running Gitlab):

$ cd /etc/nginx
$ mkdir ssl
$ cd ssl
$ openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout gitlab.key -out gitlab.crt
# Enter information as requested

Configuring nginx

Now that you have your certificate, it’s time to configure nginx. So here are the changes that I made to my nginx configuration, based on the Gitlab 6.4 default. Unless explicitly specified, these options are meant for your main server {} section of Gitlab):

  1. Change the port in your listen directive to 443 and add the ssl option. The line should then read:

     listen 443 default_server ssl;
        
  2. Add the special Strict-Transport-Security header, that will tell your browser that your website wishes to only communicate via SSL (see MDN).

     add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
        
  3. Enable SSL session cache for improved performance

     ssl_session_cache shared:SSL:10m;
     ssl_session_timeout 10m;
        
  4. Configure the SSL certificate

     ssl_certificate     /etc/nginx/ssl/gitlab.crt;
     ssl_certificate_key /etc/nginx/ssl/gitlab.key;
        
  5. Configure the enabled SSL protocols (SSLv2 was excluded for security reasons, so IE6 is not supported by this configuration).

     ssl_protocols TLSv1.2 TLSv1.1 TLSv1 SSLv3;
     ssl_prefer_server_ciphers on;
        
  6. Configure enabled SSL ciphers:

     ssl_ciphers TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:TLS_RSA_WITH_AES_256_CBC_SHA256:TLS_RSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:TLS_RSA_WITH_3DES_EDE_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:TLS_RSA_WITH_AES_128_CBC_SHA256:TLS_RSA_WITH_AES_128_CBC_SHA:HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!AESGCM;
        

    Admittedly, that last line can be a little scary, but it simply lists all SSL ciphers that you’d like to support. The list is based on Google’s current settings, but excluding RC4 (which is fast, but assumed to be broken) and old ciphers (based on this blog post).

  7. Last but not least, you probably want to redirect all non-SSL traffic, for which you add the following section to your config:

     server {
         listen 80 default_server;
         server_name ;
    
         rewrite ^ https://$server_name$request_uri? permanent;
         add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
     }
        

This should be all, as far as nginx is concerned :) For reference, my full nginx configuration can be found here.

Configuring Gitlab

Navigate to your Gitlab directory and fire up your favorite editor for config/gitlab.yml. Change the port to 443 and set https to true. In my case, I also had to disable Gravatar, which for some reason was not fetching the images from their HTTPS URLs.

Configuring gitlab-shell

Additionally, you need to edit your Gitlab Shell configuration, which can be found in the config.yml file in your gitlab-shell directory.

Here you need to change the gitlab_url option to use https:// instead of http://. Also set self_signed_cert to true if you, like me, are using a self-signed certificate.

Wrapping up

Now that the configuration part is done, we’re ready to restart nginx and Gitlab.

$ sudo service gitlab start
$ sudo service nginx restart

And to make sure that everything is working properly, I recommend running a full Gitlab check:

$ cd /home/git/gitlab && sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production

Especially make sure that “Check GitLab API access” is OK, because otherwise cloning/pushing to repositories will not work at all.


Thanks for reading, and please leave a comment if there is anything I can improve or if you just want to say hi!

Resources

  1. If this is not an option for you, you have to pay for a certificate signed by a trusted certificate authority. How to obtain such a certificate is out of the scope of this guide, though.