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


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

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.

git clone /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.

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


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.

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.

nano /etc/nginx/sites-enabled/default

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

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:

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

Finally, reload nginx.

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.

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

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

nano /etc/nginx/nginx.conf

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

http {
  # Main nginx settings will be here

Inside of the http block, paste the following settings:

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 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.

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.

/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:

/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.

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.

server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/;
  ssl_certificate_key /etc/letsencrypt/live/;

  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