Setting up SSL certificates with Let's Encrypt

on July 06, 2016. in Development, Software. A 3 minute read.

SSL Report Summary

This past week I finally got around to setting up SSL certificates using Let’s Encrypt. Let’s Encrypt is an open certificate authority that provides free SSL/TLS certificates. It’s goal is to make creating, renewing and using SSL certs painless.

And it most certainly is. I was expecting a lot more hassle to set up all this, but it was really easy to do.

Install certbot

Certbot is a Let’s Encrypt client that helps setting up a certificate by obtaining and installing it on your servers. There are many more clients out there, but certbot is the recommended one to use.

I simply installed certbot using dnf:

sudo dnf install certbot

but if your OS has no package for it yet, there’s always the manual way.

Creating a certificate

Certbot has a number of plugins that can be used to create and install a certificate on a server. I chose the webroot plugin which only gets the certificate for me and leaves the webserver configuration up to me.

sudo certbot --text --renew-by-default --agree-tos --webroot \
--email youremail@domain.tld \
--domains domain.tld,www.domain.tld \
--webroot-path /path/to/site/public \

This will create the certificate and it’s private key in the /etc/letsencrypt/live/domain.tld/ directory.

Configuring nginx

The next step is to configure nginx by enabling SSL, providing the paths to the certificate and the private key, and which protocols and ciphers to use. I added these to the server block:

listen 443 ssl;

ssl on;
ssl_certificate /etc/letsencrypt/live/domain.tld/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain.tld/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

After restarting nginx, you should be able to load up your site through https. Just remember to allow traffic on the 443 port:

sudo firewall-cmd -add-service=https --permanent
sudo firewall-cmd reload

Additional configuration

To further harden the Diffie-Helman key exchange, create new parameters for it using openssl:

sudo mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
sudo openssl dhparam -out dhparams.pem 2048

I told nginx to use it by adding it to the same server block where I set up the SSL configuration:

ssl_dhparam /etc/nginx/ssl/dhparams.pem;

I also did some SSL optimizations and enabled Strict Transport Security:

ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_buffer_size 8k;
add_header Strict-Transport-Security max-age=31536000;

This blog post explains HTTP Strict Transport Security nicely.

All this and my website gets an A+ rating on the Qualys SSL Server Test.

Enable OCSP stapling

Thanks to Goran Jurić for pointing out to enable OCSP stapling. I did so by adding this to the nginx server config:

ssl_stapling on;
ssl_stapling_verify on;

According to the nginx documentation the ssl_trusted_certificate directive is needed only when the ssl_certificate file does not contain intermediate certificates, but the fullchain.pem created by Let’s Encrypt does contain them, so I’m skipping that.

To test whether OCSP stapling is enabled, reload nginx, and from a local terminal run the following:

openssl s_client -connect domain.tld:443 -status

The output should have something like:

OCSP response:
OCSP Response Data:
    OCSP Response Status: successful (0x0)
    Response Type: Basic OCSP Response
    Version: 1 (0x0)
    Responder Id: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3