How to create and install a complete SSL certificate chain in GitLab
Description
GitLab requires a complete certificate chain to establish trust between the server and clients. You might need to build a full chain certificate under the following situations:
- You are setting up a new GitLab instance and want to add an SSL certificate
- You need to rotate an expiring SSL certificate in an existing GitLab instance
If using SSL certificates from untrusted or unrecognized certificate authorities (CAs) you might see:
- Security warnings in web browsers when accessing the GitLab user interface.
- Certificate-related errors during Git operations over HTTPS.
- Common SSL errors listed in our documentation.
Environment
-
Impacted offerings:
- GitLab Self-Managed
Prerequisites
SSL certificate files from your Certificate Authority (CA):
- Domain certificate (
domain.crt
) - Private key (
domain.key
) - Intermediate certificate(s) (
intermediate.crt
) - Root certificate (
root.crt
)
Some CAs may combine the intermediate/root certificates into a single file like chain.crt
or similar.
If you have purchased an SSL certificate, the vendor should be able to provide you with all of the certificates that make up the full chain.
It's also possible to generate the full certificate chain by entering just the Domain certificate into a site such as whatsmycertchain.com. This is not possible for internal CA based certificates.
All certificates must be in PEM format. PEM-encoded certificates can use '.crt' or '.pem' file extensions. However, the file content, not the extension, determines the format. To verify format:
- Open the certificate file in a text editor.
- Confirm it starts with
-----BEGIN CERTIFICATE-----
.
Resolution
-
Combine the certificates into one file in the following order:
- Domain certificate (your site's certificate)
- Intermediate certificate(s) (if you have them - there might be multiple)
- Root certificate
Note: GitLab will automatically use your certificate without additional configuration if the filename matches the
external_url
set in/etc/gitlab/gitlab.rb
. For example, if yourexternal_url
is'https://gitlab.example.com'
, name your certificategitlab.example.com.crt
. To use a different naming convention, review the configure HTTPS manually docs.# If your certificates are all in separate files cat domain.crt intermediate.crt root.crt > gitlab.example.com.crt # If your CA has provided you with a chain already cat domain.crt chain.crt > gitlab.example.com.crt
The resulting
gitlab.example.com.crt
file should look like this:-----BEGIN CERTIFICATE----- Your Domain certificate (or main SSL certificate): domain.crt -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- Your Intermediate certificate: intermediate.crt -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- Your Root certificate: root.crt -----END CERTIFICATE-----
-
Verify the full chain certificate:
-
To view the certificate chain from top to bottom, run:
openssl crl2pkcs7 -nocrl -certfile gitlab.example.com.crt | openssl pkcs7 -print_certs -noout | grep -E "subject=|issuer="
-
Confirm the chain output
- The top certificate
subject
should match the domain name of the GitLab instance (gitlab.example.com
) - The
issuer
should match the next certificate'ssubject
(DigiCert Intermediate CA
). Confirm this for each certificate in the chain - The chain ends with the root certificate, where subject and issuer are identical (
DigiCert Root CA Inc
)
# Example output # Domain Certificate (Your GitLab instance certificate) subject=CN = gitlab.example.com issuer=CN = DigiCert Intermediate CA # Intermediate Certificate subject=CN = DigiCert Intermediate CA issuer=CN = DigiCert Root CA Inc # Root Certificate subject=CN = DigiCert Root CA Inc issuer=CN = DigiCert Root CA Inc
- The top certificate
-
-
Copy the certificate chain and private key to
/etc/gitlab/ssl
:sudo cp gitlab.example.com.crt /etc/gitlab/ssl/ sudo cp domain.key /etc/gitlab/ssl/gitlab.example.com.key
-
Set the correct permissions:
sudo chmod 600 /etc/gitlab/ssl/gitlab.example.com.* sudo chown root:root /etc/gitlab/ssl/gitlab.example.com.*
-
Reconfigure and restart NGINX:
sudo gitlab-ctl reconfigure sudo gitlab-ctl restart nginx # If you are updating an existing SSL certificate, you can reload NGINX instead sudo gitlab-ctl hup nginx
-
Access your GitLab instance via your browser to confirm there are no certificate warnings.