Instant SSL for GitLab via Let's Encrypt
Let's Encrypt for GitLab
Right now configuring SSL requires an administrator to already have certificates, place them in specific directories, and then set up
We have an opportunity with Let's Encrypt however to make SSL easier to use out of the box. LE offers a method for requesting widely trusted certificates in an automated way, with security through an online validation process.
There are two general paths:
- Autodetect incoming host names, then attempt to generate certificates for these. This is similar to how Caddy and OpenResty (an NGINX mod) work.
- A new CLI option to run pre-flight checks to ensure the LE request is successful, and gather as much information as we can. Then the full reconfigure can process the LE certificates.
Auto-registration of hostnames in inbound requests
This is the ideal method of generating certificates, as there is no need for any DNS entry ahead of time. As requests are routed to the GitLab server, we would generate SSL certificates on the fly for the hostnames used. This offers a nice method to reduce the amount of configuration required, and you have good confidence that the DNS names are live as well. The only validation left would be to ensure that the host names used are internet reachable.
There seems to be two methods of achieving this:
In examining these options:
- Caddy would be a replacement for NGINX, which is deeply integrated throughout the product. Caddy is also less mature, and less performant. This would ultimately be a very large change to support SSL.
- The NGINX mod has a large number of dependencies including some hot patches of NGINX. As such, it looks fairly fragile and doesn't support the current version of NGINX that we bundle.
Unfortunately it looks like neither of these solutions would be particularly tenable.
Preflight checklist with integrated Let's Encrypt
Another option is to add a new option to
gitlab-ctl, or an entirely new CLI command, which runs essentially a "preflight checklist" to ensure the LE SSL requests would succeed based on the current configuration. If not, we would provide helpful and clear messages indicating what action needs to take place.
This is a very do-able solution, although not as transparent or seamless as the automatic registration above.
Proposed preflight flow
1. Check for DNS names
Check for configured DNS names within
gitlab.rb. If DNS names have not been set, attempt to detect the DNS name. We can use cloud service provider API's like we do today with AWS, or in the event that doesn't work attempt a reverse lookup.
2. Validate DNS names are internet reachable
Because LE requires internet connectivity to validate the DNS names (or direct control of a DNS server, which we don't have), we need to ensure the DNS names are reachable from the internet.
We can achieve this by simply running a LE request to the Staging API's, which have very lax rate limits and would not count against our production usage.
We should do this with a request for a single certificate with all required names (registry, etc.). Pages is not required as it will not work, as LE does not yet support wildcard certificates until 2018.
3. Request production LE certificates
With validation of internet reachability through the use of the Staging API, we should have pretty strong confidence in success. Only potential issues should be rate limits, which we won't know until we try.
We should also consider including the administrators email, as expiration warnings are sent as well as the option to recover the keys.
For configuration, we can consider using
certbot's nginx plugin, which automates the API calls and adds the necessary configuration. This should also make renewal easier, as well.
We should consider a way to automate the renewal process, as the certificates expire every 90 days. However since this requires a restart and brief outage of NGINX, that may be a challenge. Utilizing
certbot should however make the actual renewal process easier.