Using Let's Encrypt to add SSL to GitLab

I just used Let’s Encrypt to set up SSL on my personal GitLab site, and wanted to record a few notes about the process, in case it helps anybody else.


I installed GitLab from source (before the Omnibus installer), and have been running it in http-only mode for a while now. I host it myself, on Linode. (Full-disclosure: That’s a referral link.)

I really like self-hosting Gitlab, because I can have as many private repositories as I want, and have full control over the site and backups etc. And, I’m just starting to set up GitLab CI Runners, which I think will be very useful too. Importantly, I’ve found that maintainence has been pretty painless. GitLab has frequent releases, but a well-document upgrade process, which have always gone smoothly.

I pieced together these instructions from a few places, including the Let’s Encrypt - Getting Started documentation, the GitLab Instalation instructions, and this older blog post, which was outdated mostly with the GitLab details.


The main trick was that GitLab runs behind nginx, and letsencrypt doesn’t automatically support nginx yet, so I did the certificate request using the standalone mode. I didn’t set it up for auto-refresh (but did create a calendar reminder to myself to refresh it before it expires).

The other gotcha was with making the certs readable to the gitlab-shell process. See notes below.


All of the follow commands are run from the admin user at my Linode instance, so login there first:

$ ssh admin@mylinode

Start by getting the letsencrypt repo.

$ cd ~
$ git clone

Set up a config file for running letsencrypt-auto.

$ mkdir letsencrypt-config
$ vim letsencrypt-config/gitlab.ini


# This is the Let's Encrypt config for our gitlab instance
authenticator = standalone
# Generate certificates for the specified domains.
domains =
# Register certs with the following email address
email =
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

I found it simplest to just temporarily stop nginx and use the standalone mode of letsencrypt-auto (which we specified in the config file).

$ sudo service nginx stop
$ sudo mkdir /var/www/letsencrypt
$ sudo letsencrypt/letsencrypt-auto certonly -c letsencrypt-config/gitlab.ini

If it goes well, it should show output like:

    - Congratulations! Your certificate and chain have been saved at
     /etc/letsencrypt/live/ Your cert will
     expire on 2016-06-18. To obtain a new version of the certificate in
     the future, simply run Let's Encrypt again.

Put nginx back to normal:

$ sudo service nginx start

Update GitLab to use SSL

Make a copy of the certs into a new dir, specific for GitLab (see the Pitfall below for more info about why).

$ sudo mkdir -p /etc/gitlab/ssl
$ sudo cp /etc/letsencrypt/live/{cert,chain,fullchain,privkey}.pem /etc/gitlab/ssl/.
$ sudo chown -R git:git /etc/gitlab
$ sudo chmod -R 700 /etc/gitlab
$ sudo chmod 600 /etc/gitlab/ssl/{cert,chain,fullchain,privkey}.pem

Now, update the GitLab config files.

$ cd /home/git/gitlab
$ sudo -u git -H vim config/gitlab.yml
    # Set `port: 443` and `https: true`
$ sudo -u git -H vim ../gitlab-shell/config.yml
    # set `gitlab_url` to have `https`, and add:
          ca_file: "/etc/gitlab/ssl/fullchain.pem"
          ca_path: "/etc/gitlab/ssl"

Finally, update the nginx config to the SSL version.

# Use the SSL version of the nginx config
$ sudo cp lib/support/nginx/gitlab-ssl /etc/nginx/sites-available/.
$ sudo vim /etc/nginx/sites-available/gitlab-ssl
    # Change the FQDN to (in 2 places)
    # Uptate these:
        ssl_certificate /etc/letsencrypt/live/;
        ssl_certificate_key /etc/letsencrypt/live/;
$ sudo ln -s /etc/nginx/sites-available/gitlab-ssl /etc/nginx/sites-enabled/gitlab-ssl

# Turn off the old non-SSL nginx config
$ sudo rm /etc/nginx/sites-enabled/gitlab

# Test and restart nginx
$ sudo nginx -t
$ sudo service nginx restart

Optional: Stronger Diffie-Hellman Parameters

From the “more is better” department, we might as well generate stronger Diffie-Hellman parameters while we’re in here.

To do that, just run:

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

It says “This is going to take a long time”, and for the 4096 size, it took about 10 minutes on my Linode server. Just be patient.

Then un-comment the line in the nginx.conf that has:

ssl_dhparam /etc/ssl/certs/dhparam.pem;

and restart nginx again.


Now you should be able to visit and see your GitLab site over SSL.

Update 2016-04-23

A helpful reader, Michel Nemnom, pointed out that I should test my server with SSL Labs’ awesome SSL Server Test. My original instructions here had the nginx.conf pointing the ssl_certificate at cert.pem, which caused the SSL Labs test to give me a grade of only B (because “This server’s certificate chain is incomplete”). But, simply changing that value to be the fullchain.pem, it now gives me a grade of A+. Much better! I’ve already updated this in the instructions above.

Michel also recommended generating stronger Diffie-Hellman parameters, which prompted the section about that above.