Let's Automate Let's Encrypt

After you get all the certificates, it's safe to remove the temporary directory:


rm -rf /tmp/letsencrypt

Let's go back to the nginx configuration. Getting an A+ grade from SSLLabs requires some additional effort. Create a new Ephemeral Diffie-Hellman prime (if this is the first time you've see this term, go here for more information):


sudo openssl dhparam -out /etc/pki/tls/private/dhparam.pem 4096

Caution: if you absolutely need to support ancient versions of client software, for example, Java 6 clients, you need to skip this step and comment the ssl_dhparam line in the following step. These old clients do not support Diffie-Hellman parameters longer than 1024 bytes, so you need to make a choice between supporting those clients and security.

Now, have a hot beverage; it will take some time to generate. Add these lines to the "http" section of /etc/nginx/nginx.conf:


http {
        ...
        ssl_dhparam /etc/pki/tls/private/dhparam.pem;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 60m;
        ...
}

Create a new file /etc/nginx/ssl_options.inc:


ssl on;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "ECDH+AESGCM DH+AESGCM ECDH+AES256 DH+AES256
     ↪ECDH+AES128 DH+AES ECDH+3DES DH+3DES RSA+AESGCM
     ↪RSA+AES RSA+3DES !aNULL !MD5 !DSS";
# Enable HSTS (HTTP Strict Transport Security) for half a year
add_header Strict-Transport-Security
 ↪"max-age=15768000;includeSubDomains";

And create a new "server" section:


server {
    listen 443;
    server_name example.com www.example.com;

    include /etc/nginx/letsencrypt.inc;
include /etc/nginx/ssl_options.inc;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        # enable OCSP stapling to speed up first connect
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate
     ↪/etc/letsencrypt/live/example.com/chain.pem;

...
}

Warning: the Strict-Transport-Security header will tell each visitor that you promise always to use HTTPS in the future. It's a one-way street, and once you set it, there is no way back—your visitor's browser will remember your promise and insist on having HTTPS. Also note: for more information on OCSP stapling, see this Wikipedia page.

After making all of these changes, reload the nginx configuration again:


sudo /usr/sbin/nginx -t && sudo service nginx reload

At this point, your Web site should have HTTPS up and running. Try to open https://www.example.com/ in a browser and enjoy the green lock sign in the address line. To verify the quality of encryption, go to SSL Labs SSL Server Test and submit your hostname for a check (usually it takes several minutes).

So, now that you have HTTPS, how about disabling HTTP? Go back to the HTTP "server" section and make the following improvement:


server {
    listen 80;
    server_name example.com www.example.com;
        include /etc/nginx/letsencrypt.inc;
        ...
if ($scheme = "http") {
        rewrite ^/(.*)$ https://$host/$1 permanent;
}
        ...
}

This will redirect all traffic from HTTP to HTTPS, automatically bringing all clients to the secure version of your Web site. Reload the nginx configuration to activate the changes.

Now it's time to automate certificate renewals. Let's Encrypt's current policy allows you to request five certificate renewals for a domain within seven days. That means it wouldn't be wise (and wouldn't make much sense either) to try to renew certificates every day. On the other hand, leaving it for the last moment before expiration also is quite dangerous. Luckily, there is an easy way to renew these certificates only when they have less than 30 days before expiration. To me, 30 days sounds just right. That means my certificates will be reissued every 60 days on average, and if something fails afterward, I will have a whole month to fix whatever is broken.

______________________

Andrei Lukovenko is a longtime Linux user, command-line fanboy, automation aficionado.