Let’s Encrypt – Is your website secure?

letsencrypt_logoI was searching for a good and free TLS certificate which is signed by a trusted Certificate Authority (CA). A CA is an organization for issuing digital certificates. You need to have a Certificate Authority when you want to use HTTPS, secure HTTP web server connections. You know; when you visit a secure web-page (https://) and you will see a green lock-icon in your web-browser. This icon indicates that you have an encrypted connection with this website.

In this article I will explain how TLS certification requests normally works and how Let’s Encrypt works. Let’s Encrypt is a Certificate Authority, who provides free and trusted domain certificates. Eventually, I explain how to setup Let’s Encrypt yourself using Nginx webserver.

How Certificate Requests works

In order to have a secure connection, you need a certificate (which consists of public/private keys). To get this certificate, you normally create a Certificate Signing Request (CSR). This CSR needs to be signed by a Certificate Authority. On the world there exist only a couple of ‘trusted’ certificate authorities. These root-certificates are finally trusted by your webbrowser. Too bad most of the Certificate Authorities costs money (about 18 euros per year for 1 domain). Yep, you need to pay for them.

Requesting a SSL Certificate

Requesting a TLS Certificate

Another option is to create a so called Self-signed certificate. On that moment you still need to create a private key and a certificate signing request (CSR). But instead you will sign your CSR yourself using your own private key! This is still very secure, and you still have a secure connection. Why not use it? Well, there is one down-side. Visitors who visit your webserver which uses a self-signed certificate, will get a big warning “Your connection is not private” or something similar. Your visitors will almost never continue and they are gone…

Warning you get when using Self-signed Certificate

Warning you get when using Self-signed Certificate

Let’s Encrypt

On April 12, 2016 Let’s Encypt left Beta. Let’s Encrypt makes it possible to create a trusted certificate, which is trusted by all major web-browsers. The big pro is that Let’s Encrypt is totally 100% FREE to use! Let’s Encrypt is a fully automated and open-source certificate authority. Free automated certificate authorities are the future of secure server connections.


Let’s Encrypt High-level overview

The (Nginx) server can request a certificate from Let’s Encrypt, which is free but limited up to 100 certificates per domains. There is NO limit to the number of certificates that can be issued to different domains. The end-use can use the secure TLS/SSL connection between his computer and the webserver. Renewing is needed because the Let’s Encrypt certificates are only a few tens of days valid (90 days at the moment). In the future a nginx plugin can make this even easier.

Furthermore Let’s Encrypt is one of the Linux Foundation Collaborative Projects. Big names as Cisco, Google, IBM, Intel, Qualcomm, Samsung and others are also part of the Linux Foundation Collaborative Projects.

Let’s Encrypt is created by the Internet Security Research Group (ISRG). ISRG is a California public benefit corporation.


I’m running a Debian Jessie webserver myself. You could clone the Github repository and use the certbot-auto command. Or install the latest certbot via Jessie backports. I choose to use the certbot package from the Jessie Backports.

Not long ago the package has been renamed from letsencypt to certbot. We will use the certbot package.

First enable the Backports repository in the sources.list (sudo nano /etc/apt/sources.list), add the following line:

deb http://ftp.debian.org/debian jessie-backports main

Then install the certbot package:

sudo apt-get update
sudo apt-get install certbot -t jessie-backports

Too bad Let’s Encrypt doesn’t support wildcard certificates. Instead you need to request a new certificate for every domain & sub-domain. Let’s begin with setting-up my Server webpage. First we need to be sure the .well-know directory is publicly available, needed for the webroot plugin.

Let’s Encrypt does also provide other alternatives besides Webroot plugin like Standalone Plugin and Apache plugin. More later about that.

I will edit my Nginx site configuration file first: /etc/nginx/sites-enabled/server.melroy.org. Within the server block I added:

server {
        # Let's Encrypt Webroot plugin
        location ~/.well-known {
                allow all;
                default_type text/plain;

Reload the Nginx configuration:

sudo service nginx reload

Webroot plugin

Be sure the current website is not configured to use self-signed certificates, otherwise the verification will fail at this point. Then I finally use the certbot certonly --webroot command to obtain a new certificate:

sudo certbot certonly --webroot -w /var/www/server.melroy.org/html/ -d server.melroy.org

TIP: There is currently a limit of 20 certificate requests/week. You can combine multiple domains together and this will act as 1 certificate request. This certificate can be used for multiple-domains. To do so, you can do the same request as above with more domains:

sudo certbot certonly --webroot -w /var/www/html -d www.melroy.org -d melroy.org -w /var/www/other -d other.melroy.net -d another.other.melroy.net

In the example above you would obtain a single certificate for all of those domain names (4 in total), using the /var/www/html webroot directory for the first two domains, and /var/www/other for the second two domains.

Standalone plugin

Or you could use the  --standalone parameter, when your systems has no webserver, or when direct integration with the local webserver is not supported or not desired (port 80/443 should be available when using --standaloneflag). Then do the following:

sudo certbot certonly --standalone -d server.melroy.org

Webserver Plugins

If you are using Apache, you could use the Apache plugin. Nginx server is not yet supported via the plugin system, that is why I used Webroot plugin in this tutorial.


Either way, when the request is successfully a certificate chain file will be created, in my case:


A chain consists of multiple certificates which are literally ‘chained together’. The list of the files in /etc/letsencrypt/live/server.melroy.org are:

  • cert.pem: Your domain’s certificate
  • chain.pem: The Let’s Encrypt chain certificate
  • fullchain.pem: cert.pem and chain.pem combined
  • privkey.pem: Your certificate’s private key

We will use the fullchain.pem as the certificate file, and privkey.pem as the certificate key file for the Nginx server.

Be-aware: 1024-bit keys are unsafe to use.

That is why I want to further improve the security by creating a strong Diffie-Hellman Group, which determines the strength of the key exchange (2048-bit in this case). This can take a while:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

When this is done, we continue. We will change the Nginx site configuration, in my case: /etc/nginx/sites-available/server.melroy.org:

# Redirect ALL HTTP traffic to HTTPS
server {
        listen 80 default_server;
        server_tokens off;
        return 301 https://$host$request_uri;

# HTTPS block
server {
        listen 443 ssl default_server;
        server_name server.melroy.org;
        # Don't show version number
        server_tokens off;

        # TLS Certificates
        ssl_certificate /etc/letsencrypt/live/server.melroy.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/server.melroy.org/privkey.pem;        

        # Increase security (using the Diffie-Hellman Group file)
        ssl_dhparam /etc/ssl/certs/dhparam.pem;

        ssl_protocols TLSv1.2;
        ssl_prefer_server_ciphers on;

        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:10m;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;
        # Let's Encrypt Webroot plugin
        location ~/.well-known {
                allow all;


The orange part I changed to configure Let’s Encrypt in Nginx webserver. If backwards compatibility is necessary (for Windows XP for example), use the following instead:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

However, I’m using the recommended cipher suite from Mozilla.

Now we restart the server:

sudo service nginx reload

When you visit your own website and open the server certificate, you should verify if the Common Name (CN) is equal to “Let’s Encrypt Authority X1”.

Let's Encrypt Certificate

Let’s Encrypt Certificate in Firefox

Now we can verify if the website is secure enough go to Qualys SSL Labs SSL Server Test and enter your domain name. You should get a A+ rating, like below.

server.melroy has A+ rating!

server.melroy.org has A+ rating!

Setup Renewal

Since the certificate is (currently) only 90 days valid, renewing is necessary. Although 60 days is recommended to allow some margin of error. Renewal can be triggered using the command certbot renew, which gives the output:

Processing /etc/letsencrypt/renewal/server.melroy.org.conf
The following certs are not due for renewal yet:
  /etc/letsencrypt/live/server.melroy.org/fullchain.pem (skipped)
No renewals were attempted.

After-all, the certificate is still valid. We just created it..! Nevertheless, I will create a bash script for automatically renewing the certificates, and using the --pre-hook & --post-hook parameters to stop & start the webserver again.

certbot renew --standalone --pre-hook "service nginx stop" --post-hook "service nginx start" > /var/log/letsencrypt/renew.log 2>&1
if [ "$LE_STATUS" != 0 ]; then
    echo Automated renewal failed:
    cat /var/log/letsencrypt/renew.log
    exit 1

For testing the script, add the --dry-run parameter to the certbot renew command. Don’t forget to give the script execute rights: sudo chmod +x renew.sh. Executing sudo /home/melroy/renew.sh can give you when needed:

Congratulations, all renewals succeeded. The following certs have been renewed:
  /etc/letsencrypt/live/server.melroy.org/fullchain.pem (success)

I create a cronjob which executes my script (renew.sh) every week to be sure my certificate won’t get outdated, run: sudo crontab -e, with the content:

30 2 * * 1 /home/melroy/renew.sh

This will execute the script every Monday at 2:30 AM.


Well, that’s it! Your webserver is now using a very safe TLS secure connection by using Let’s Encrypt Certificates. All free and open-source.

Good luck!

Some tips

Check Nginx configuration for any errors/warnings by executing:

sudo /usr/sbin/nginx -t

Let’s Encrypt log is:


Did you know…

  • that TLS is the successor of SSL? Despite the fact that term ‘SSL’ is more well-known, TLS  should be used by now. All SSL versions are broken and insecure.
  • that TLS (v1.0 1999) has been revised twice? TLS v1.1 (2006) and TLS v1.2 (2008).
  • a quantum computer with 1,000 qubits could easily crack encryption keys? So in the future the certificate we use today aren’t so safe anymore, even if you are using 2048 or 4096 bit keys.
    That is why you need to think TODAY about how to protect the data in the future. Especially since the  NSA can record your data today, and crack it over a few years.
  • that NSA created backdoors in hardware like CPU and encryption chips? When the hardware can’t be trusted, your are doomed. The software can encrypt the data very securely, however the hardware may send the non-encrypted data over the Internet (let’s say to NSA) before it’s encrypted. Data is in RAM isn’t encrypted. The worst of all, you just don’t know if you hardware contains any backdoors.
  • that NSA created yet another backdoor in cryptography? NSA build a backdoor in the system’s random generator. Some tools like OpenSSL used the system’s random generator. Which is a good approach if the system really returns a good random number. Unfortunately, the NSA interfered with this. Meaning you won’t get a ‘random number’ which is really random. Now, the system’s random generator is not fully trusted anymore. That’s why OpenSSL also uses its own random generator in software.
  • that in Holland almost 20% of the local authorities (Gemeenten) still uses the very insecure SSLv2? Whereby personal data is almost literally open for the public. 1)
Did you like the article? Please share!