This guide is written for Ubuntu/Debian. If you run any other distribution of linux, this guide may not be for you.

Let's Encrypt on linux 2016-05-22
A full guide on setting up Let's Encrypt as a certificate provider on Linux. Written by a human, for humans.

Let's Encrypt is a free, automated and open certificate authority (CA).
It is a great tool for developers who want SSL on their websites. Not only that, did i mention it's completely free?

Let's Encrypt

Installation

First of all we need to install some dependencies before installing Let's Encrypt.

root
apt-get update
apt-get -y install git bc

Now we can download the Let's Encrypt ACME API client named Certbot.
We will download it to /opt/letsencrypt as that is the most common location for it.

root
git clone https://github.com/certbot/certbot.git /opt/letsencrypt

Automatic renewal

For convenience, Let's Encrypt has a command to renew all certificates. Let's use that command to automatically update our certificates.
Enter this to bring up a text editor for your crontab.

root
crontab -e

This should bring up a text editor for the crontab
At the bottom of this file, place the following lines:

30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/le-renew.log
35 2 * * 1 /etc/init.d/nginx reload

Webroot

To sign certificates, the Let's Encrypt API needs to verify that you own the domain for the certificate.
The easiest strategy for doing this is called webroot.

To begin setting up a webroot, create a folder for the webroot.

root
mkdir /var/www/letsencrypt-webroot

Next up we need to set up nginx to serve this webroot under all domains we want Let's Encrypt certificates for.
The easiest way to serve the Let's Encrypt webroot for all domains is to edit the default config. On new installations, the default config has the path below.

root
nano /etc/nginx/sites-enabled/default

In the text editor, look for the default server, it should look somewhat like this:

nginx
server {
	listen 80 default_server;
	listen [::]:80 default_server ipv6only=on;

	root /usr/share/nginx/html;
	index index.html index.htm;

	# Make site accessible from http://localhost/
	server_name localhost;

	# ...
}

Inside of the server block, paste the following settings:

nginx
location ~ /.well-known {
  allow all;
  alias /var/www/letsencrypt-webroot/.well-known;
  try_files $uri $uri/ =404;
}

Finally, reload nginx.

root
nginx -s reload

Nginx SSL configuration

By default, nginx has a very weak SSL configuration. Let's fix that.
First of all, we need to generate a strong set of Diffie-Hellman parameters.

root
openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

Now let's open up a text editor and edit the nginx configuration.

root
nano /etc/nginx/nginx.conf

In the text editor, find the http block. It should look somewhat like this:

nginx
http {
  # Main nginx settings will be here
}

Inside of the http block, paste the following settings:

nginx
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
add_header Strict-Transport-Security "max-age=63072000; always";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

There are a lot of settings that can be explained here, but I'm not going to. If you need any explanation, please look at the nginx documentation.
All i will tell you is that these settings are the perfect combination of security and backwards compatibility.
Finally, reload nginx.

root
nginx -s reload

Certificate creation

Now that we've installed Let's Encrypt, set up automatic renewal, set up a webroot and configured nginx optimally for security, let's create a few certificates!
I am going to demonstrate how to create 4096-bit certificates, because a stronger bitlength than 2048 is becoming the new standard. You could also use 3072 here as that is the logical step up from 2048.

root
/opt/letsencrypt/letsencrypt-auto -a webroot --rsa-key-size 4096 --webroot-path /var/www/letsencrypt-webroot certonly

Entering this command should bring up a nice user interface where you can enter several domains to create a certificate for.
If you don't add the domain to the server_name block in /etc/nginx/conf.d/letsencrypt.conf and reload nginx before doing this, you will encounter an error and not be able to create a certificate for that domain until you do so.

I recommend placing this command in a shellscript so you can easily run it without forgetting it. To do so, place this code in a file somewhere:

#!/bin/bash
/opt/letsencrypt/letsencrypt-auto -a webroot --rsa-key-size 4096 --webroot-path /var/www/letsencrypt-webroot certonly

After placing the code in a file, we need to make the file executable.

root
chmod +x /path/to/script

Certificate usage

I'm not going to go into detail on how to make an nginx virtual host, but this is an example of a virtual host using the certificates created in the previous step.

nginx
server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  server_name example.com;

  location / {
	  default_type text/html;
	  return 200 "<h1>Hello world!</h1>";
  }
}

Thanks for reading!

I hope you were able to follow the guide without any problems, if you have any questions please feel free to contact me!

 

Written by
Alexander Sagen