Secure Nginx with SSL and Let's Encrypt

Hint: If you do not want to install the client and all software needed by it on your web server you can also try getting a certificate with the help of this website which leeds you through the steps to manually request a certificate.

On December 3rd, 2015 Let’s Encrypt entered Public Beta. So now you can get a SSL certificate for free without waiting period. At home I use a Cubietruck (device similar to the Raspberry Pi) as ny own personal cloud. Here I want to show how I configured Nginx with a SSL certificate from Let’s Encrypt.

At first you have to install the Let’s Encrypt client installiert. The installer downloads and installs debian packages needed and sets up an environment for the client in ~/.local/share:

hostname:~# git clone https://github.com/letsencrypt/letsencrypt
hostname:~# cd letsencrypt
hostname:~/letsencrypt# ./letsencrypt-auto

For Nginx there is no plugin which installs the certificate automatically included. So you have to use standalone as plugin und adopt the Nginx configuration by yourself. To validate the domain (to make sure you actually are the owner of the domain) ports 80 and 443 are used by the client. Since they are already used by Nginx you need to stop the web server while using the client to get your certificate. In my case a short downtime of the web server is no problem (in the end it is only a service for myself). If this is no option you can also validate the domain with some files in the web root werden.

hostname:~# sudo /etc/init.d/nginx stop
hostname:~# ./letsencrypt-auto certonly -d example.krausmueller.de
hostname:~# sudo /etc/init.d/nginx start

If everything succeeded you find the files belonging to the certificate in /etc/letsencrypt/live/example.krausmueller.de/:

hostname:~# sudo ls /etc/letsencrypt/live/example.krausmueller.de/
cert.pem  chain.pem  fullchain.pem  privkey.pem

Besides the certificate you should create your own Diffie-Hellman parameters :

hostname:~# sudo openssl dhparam -out /etc/nginx/dhparams.pem 2048

To get a pretty secure Nginx configuration you can use the Mozilla SSL Configuration Generator. Make sure to specify the correct versions of Nginx and OpenSSL. In my case I got this configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
    listen 443 ssl;
    server_name example.krausmueller.de;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /etc/letsencrypt/live/example.krausmueller.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.krausmueller.de/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /etc/nginx/dhparams.pem;

    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

}

After a restart of Nginx you should get an “A rating” at SSL Labs.

SSL Labs Rating

Certificates from Let’s Encrypt are only valid for 90 days. Because of this you have to renew them regularly. You can automate this with a cron job. This example renews the certificate every second month on the 28th day of the month:

hostname:~# crontab -l
# m   h    dom mon           dow   command
  0   1    28  2,4,6,8,10,12 *     sudo /etc/init.d/nginx stop; /home/user/letsencrypt/letsencrypt-auto certonly --renew -d example.krausmueller.de; sudo /etc/init.d/nginx start