keepcalculator

06 Numbers and Powers

How to Set Up SSL on a Self-Hosted GitLab Server

Card No. 06·31988 · Updated · Standard formula, shown below

This guide walks you through enabling HTTPS on your self-hosted GitLab instance using Let’s Encrypt certificates. You’ll get encrypted traffic between users and your GitLab server, which is essential for protecting credentials and repository data. We cover both automatic and manual certificate installation, plus how to renew and troubleshoot.

What You’ll Need

  • A self-hosted GitLab server (Omnibus package recommended) with root or sudo access.
  • A domain name pointing to your server’s public IP address (e.g., git.example.com).
  • Ports 80 and 443 open in your firewall and reachable from the internet (Let’s Encrypt uses port 80 for validation).
  • Basic familiarity with the command line and editing GitLab’s configuration file (/etc/gitlab/gitlab.rb).

Step-by-Step

  1. Update GitLab and check the version
    SSH into your server and run sudo apt update && sudo apt upgrade (or your distro’s equivalent). Ensure you’re on a recent GitLab version that supports Let’s Encrypt integration (14.0+ recommended).
  2. Set your external URL to HTTPS
    Edit /etc/gitlab/gitlab.rb and find the line external_url 'http://git.example.com'. Change it to external_url 'https://git.example.com'. Use your actual domain.
  3. Enable Let’s Encrypt (automatic method)
    In the same file, add or uncomment these lines:
    letsencrypt['enable'] = true
    letsencrypt['contact_emails'] = ['admin@example.com']
    letsencrypt['auto_renew'] = true
    Set auto_renew to true to keep certificates valid automatically.
  4. Reconfigure GitLab
    Run sudo gitlab-ctl reconfigure. This will generate a self-signed certificate first, then request a real certificate from Let’s Encrypt. The process may take a few minutes.
  5. Verify the certificate
    After reconfigure finishes, visit https://git.example.com in a browser. You should see a valid lock icon. Also run sudo gitlab-ctl status to ensure all services are running.
  6. Manual certificate installation (if you have your own cert)
    If you prefer to use a certificate from another CA, place your certificate and key files on the server (e.g., in /etc/gitlab/ssl/). Then edit gitlab.rb and add:
    nginx['ssl_certificate'] = "/etc/gitlab/ssl/git.example.com.crt"
    nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/git.example.com.key"
    Make sure the files are readable by the gitlab user, then reconfigure.
  7. Redirect HTTP to HTTPS (optional but recommended)
    In gitlab.rb, set nginx['redirect_http_to_https'] = true to force all traffic to use HTTPS. Reconfigure again.
  8. Test renewal (for Let’s Encrypt)
    Run sudo gitlab-ctl renew-le-certs to manually trigger a renewal. If it fails, check the logs at /var/log/gitlab/lets-encrypt/.

Common Mistakes

  • Forgetting to open port 80 – Let’s Encrypt validation requires HTTP access. If port 80 is closed, the certificate request fails.
  • Using an IP address as external_url – Let’s Encrypt does not issue certificates for bare IP addresses. You must use a domain name.
  • Not updating DNS before requesting – The domain must resolve to your server’s public IP. Check with dig git.example.com.
  • Editing gitlab.rb but not reconfiguring – Changes take effect only after gitlab-ctl reconfigure.
  • Setting wrong file permissions on manual certs – The gitlab user must be able to read the certificate and key files. Use chmod 600 on the key.

Tips

  • Use a dedicated subdomain like git.example.com rather than the root domain – it’s cleaner and easier to manage.
  • Set up a firewall rule to allow only ports 80 and 443 from the internet; keep SSH on a non-standard port or restrict by IP.
  • If you’re behind a reverse proxy (like Nginx or Apache), you’ll need to configure SSL at the proxy level, not in GitLab. In that case, set external_url to the HTTPS URL and disable GitLab’s own SSL termination.
  • Monitor certificate expiry with a cron job that checks the expiration date and alerts you via email.
  • For high-traffic instances, consider using a CDN or load balancer with SSL termination, but be aware of the added complexity.

Troubleshooting

Certificate request fails with “Connection refused”
Check that port 80 is open and that no other service is blocking it. Run sudo netstat -tulpn | grep :80 to see what’s listening. If GitLab’s nginx isn’t running, start it with sudo gitlab-ctl start nginx.

Browser shows “Your connection is not private”
This usually means the certificate is not trusted. Check the certificate chain with openssl s_client -connect git.example.com:443 -showcerts. If the certificate is self-signed, you probably didn’t enable Let’s Encrypt correctly – recheck your gitlab.rb settings.

Reconfigure hangs or times out
This can happen if the server can’t reach Let’s Encrypt’s servers. Check outbound HTTPS (port 443) connectivity. Also, ensure your system time is correct – run date and fix with sudo ntpdate pool.ntp.org if needed.

Renewal fails with rate limit
Let’s Encrypt has rate limits. If you’ve requested too many certificates, wait a week or use the staging environment for testing. Set letsencrypt['staging'] = true to test without hitting limits.

After enabling HTTPS, GitLab is inaccessible
Check the nginx error log: sudo tail -f /var/log/gitlab/nginx/error.log. Common issues include port conflicts or misconfigured certificate paths. Revert the external_url change if needed.

Mixed content warnings in the web UI
If you have any hardcoded http:// URLs in your project settings or webhooks, update them to https://. Also, clear your browser cache.

Frequently Asked Questions

Q: Can I use a free certificate from Let’s Encrypt for a production GitLab server?
A: Yes, Let’s Encrypt certificates are trusted by all major browsers and are perfectly fine for production use. They last 90 days, but GitLab’s auto-renewal handles it.

Q: Do I need to stop GitLab to install a certificate?
A: No, you can apply a new certificate without downtime. Just update the configuration and run gitlab-ctl reconfigure – it will reload nginx gracefully.

Q: What if my GitLab is behind a NAT or reverse proxy?
A: Then the SSL certificate should be installed on the proxy, and GitLab itself can use plain HTTP internally. Set external_url to the public HTTPS URL and disable GitLab’s nginx SSL.

Q: How do I force all users to use HTTPS?
A: Set nginx['redirect_http_to_https'] = true in gitlab.rb and reconfigure. This will redirect any HTTP request to HTTPS.

Q: Can I use a wildcard certificate?
A: Yes, you can use a wildcard cert for *.example.com. Place it in the SSL directory and configure nginx as described in the manual method. Let’s Encrypt supports wildcards via DNS validation, but GitLab’s built-in integration doesn’t support that – you’d need to obtain the wildcard manually.

Q: How do I check when my certificate expires?
A: Run echo | openssl s_client -servername git.example.com -connect git.example.com:443 2>/dev/null | openssl x509 -noout -dates. This shows the notAfter date.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →