Getting GitLab CE to work with SSL and intermediate certificates

Our research lab is non-profit, but private GitHub repositories still cost money, so I have been playing with GitLab Community Edition to serve up some private Git repositories from a third-party host on the cheap.

Before using GitLab CE, I had set up a Git repository that, for whatever reason, would not allow users to cache credentials and would also not allow access via https (SSL). It was getting pretty frustrating to have to type in a long string of credentials on every commit, so setting up a proper Git server was one of the goals.

Installing and setting up the server is pretty painless. After installing all the necessary files and editing the server’s configuration file, I go into the GitLab web console and add myself as a user, and then add myself as a master of a test repository called test-repo.

When I try to clone this test repository via https, I get a Peer's Certificate issuer is not recognized error, which prevents cloning.

To debug this, Git uses the curl framework, which I put into verbose mode:

$ export GIT_CURL_VERBOSE=1

When cloning, I get a bit more detail about the certificate issuer error message:

$ git clone https://areynolds@somehost.lab.org:9999/areynolds/test-repo.git Cloning into 'test-repo'... * Couldn't find host somehost.lab.org in the .netrc file; using defaults * About to connect() to somehost.lab.org port 9999 (#0) * Trying ... * Connection refused * Trying ... * Connected to somehost.lab.org (127.0.0.1) port 9999 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * failed to load '/etc/pki/tls/certs/renew-dummy-cert' from CURLOPT_CAPATH * failed to load '/etc/pki/tls/certs/Makefile' from CURLOPT_CAPATH * failed to load '/etc/pki/tls/certs/localhost.crt' from CURLOPT_CAPATH * failed to load '/etc/pki/tls/certs/make-dummy-cert' from CURLOPT_CAPATH * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: /etc/pki/tls/certs * Server certificate: * subject: CN=*.lab.org,OU=Domain Control Validated * start date: Oct 10 19:14:52 2013 GMT * expire date: Oct 10 19:14:52 2018 GMT * common name: *.lab.org * issuer: CN=Go Daddy Secure Certificate Authority - G2,OU=http://certs.godaddy.com/repository/,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US * NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER) * Peer's Certificate issuer is not recognized. * Closing connection 0 fatal: unable to access 'https://areynolds@somehost.lab.org:9999/areynolds/test-repo.git/': Peer's Certificate issuer is not recognized.

Something is up with the certificate from Go Daddy. From some Googling around, it looks like nginx doesn’t like using intermediate certificates to validate server certificates.

To fix this, I concatenate my wildcard CRT certificate file with GoDaddy’s intermediate and root certificates, which are available from their certificate repository:

$ sudo su - # cd /etc/gitlab/ssl # wget https://certs.godaddy.com/repository/gdroot-g2.crt # wget https://certs.godaddy.com/repository/gdig2.crt # cat somehost.lab.org.crt gdig2.crt gdroot-g2.crt > somehost.lab.org.combined-with-gd-root-and-intermediate.crt

I then edit the GitLab configuration file to point its nginx certificate file setting to this combined file:

... ################ # GitLab Nginx # ################ ## see: https://gitlab.com/gitlab-org/omnibus-gitlab/tree/629def0a7a26e7c2326566f0758d4a27857b52a3/doc/settings/nginx.md # nginx['enable'] = true # nginx['client_max_body_size'] = '250m' # nginx['redirect_http_to_https'] = true # nginx['redirect_http_to_https_port'] = 443 nginx['ssl_certificate'] = "/etc/gitlab/ssl/somehost.lab.org.combined-with-gd-root-and-intermediate.crt" ...

Once this is done, I then reconfigure and restart GitLab the usual way:

$ sudo gitlab-ctl reconfigure $ sudo gitlab-ctl restart

After giving the server a few moments to crank up, I then clone the Git repository:

$ git clone https://areynolds@somehost.lab.org:9999/areynolds/test-repo.git Password for 'https://areynolds@somehost.lab.org:9999': ...

I can even cache credentials!

$ git config credential.helper store

Much nicer than the previous, non-web setup.