Let's encrypt - free SSL certificates quick guide (Nginx)

20th November 2015 – 810 words

Let’s encrypt, an initiative by the Internet Security Research Group (consisting of Mozilla, EFF, Cisco, Akamai, …) will launch on Dec 3rd 2015 in public beta. Until then, you can already take part in the private beta, which I found rather painless. Free SSL for everybody!

Beta registration (valid until 3rd dec 2015)

First, register your domains + subdomains with the Google Form. You can add any number of domains and subdomains (some people report numbers of 100 domains worked1). You need to add the “www.YOURDOMAIN.com” separately to the “YOURDOMAIN.com”. You will receive an email when your domains are unlocked for beta (for me, took about 1 day). Letsencrypt will filter out Alexa Top 1000 domains2.

Nevertheless, you can still carry on installing the tools. Just use the staging server, which will work the same, just issue untrusted certificates.

Tool installation

Letsencrypt supports various installation methods. I just used the git checkout with the letsencrypt-auto tool.

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

Letsencrypt auto will install missing packages and place itself under ~/.local/share/letsencrypt/bin/letsencrypt.

Running webroot plugin

Letsencrypt also supports various authentication strategies. Depending on your setup, you could also try out the full automatic Apache2 method. I went with webroot plugin, which places a challenge file in a your website’s web-folder or as a separate location. Together with 3 lines Nginx config, this worked great. Most of the guide I borrowed3 from posts from the Letsencrypt Discourse community

Some command line options options can be specified in a config file to make re-running simpler:

# ~/webroot.ini

rsa-key-size = 2048

# Staging server -> use this in the beginning
server = https://acme-staging.api.letsencrypt.org/directory

# beta server, use this if you received the email from letsencrypt
# server = https://acme-v01.api.letsencrypt.org/directory

# Uncomment and update to register with the specified e-mail address
email = admin@mydomain

# Uncomment to use a text interface instead of ncurses
text = True
agree-tos = True
agree-dev-preview = True
renew-by-default = True

authenticator = webroot

Next, modify your Nginx server definition to catch the incoming authentication requests:

# /etc/nginx/sites-enables/mydomain
server {
  listen 80;
  server_name example.com;

  location /.well-known/acme-challenge {
    root        /etc/letsencrypt/webrootauth;
    default_type "text/plain";
  }
	#... config
}

Create that folder and reload Nginx

sudo mkdir /etc/letsencrypt/webrootauth
sudo service nginx reload

Now, run the letsencrypt tool:

sudo ~/.local/share/letsencrypt/bin/letsencrypt auth \
    --webroot-path /etc/letsencrypt/webrootauth \
    -c ~/webroot.ini \
    -d example.com -d www.example.com

AFAIK, you can specify up to 100 domains with the -d parameter. Just make sure, all those domain’s A records resolve to your host and all Nginx sites are modified as above!

If you received the beta invite mail, just swap out the beta server in the webroot.ini and run the command again!

Using SSL certs

If everything works, Letsencrypt will create a bunch of folders under /etc/letsencrypt. Your most update certificates will be placed in /etc/letsencrypt/live/example.com/. To enable SSL, just use those certificate + key:

# /etc/nginx/sites-enabled/mydomain_ssl
server {
  listen 443 ssl;
  server_name example.com www.example.com;

  include /etc/nginx/nginx-ssl.conf;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  # ...
}

As you can see, I include a nginx-ssl.conf, with some default SSL config:

# /etc/nginx/nginx-ssl.conf
# based upon https://gist.github.com/konklone/6532544
ssl on;
add_header Strict-Transport-Security max-age=31536000;
ssl_prefer_server_ciphers on;
ssl_ciphers 'kEECDH+ECDSA+AES128 kEECDH+ECDSA+AES256 kEECDH+AES128 kEECDH+AES256 kEDH+AES128 kEDH+AES256 DES-CBC3-SHA +SHA !aNULL !eNULL !LOW !MD5 !EXP !DSS !PSK !SRP !kECDH !CAMELLIA !RC4 !SEED';

# IE 6 support needed? if yes uncomment :(
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;

ssl_session_cache   shared:SSL:10m;
ssl_session_timeout 10m;
keepalive_timeout   70;

spdy_headers_comp 0;

# if you have a dhparam.pem use it here
# you can generate that file:
# openssl dhparam -rand - 2048 >> /etc/nginx/ssl/dhparam.pem creates=/etc/nginx/ssl/dhparam.pem
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

ssl_stapling on;
ssl_stapling_verify on;
resolver 127.0.0.1 valid=86400;
resolver_timeout 10;

Going further

  • Letsencrypt does not support wildcard certificates, so you need to specify and authenticate each subdomain separately. But those can be bundled in a certificate with up to 100 alternate names.
  • LE’s certificates are only valid for 90 days, so you need regular reissuing, maybe add a Cronjob script that runs the letsencrypt command with --renew flag with a following service nginx reload.
  • The beta server is heavily rate limited (only 10 registrations per day per server right now). If unsure, use the staging server first.
  • Interestingly, .de TLD’s are second most popular after .com Letsencrypt statistics

Happy hacking!

  1. https://community.letsencrypt.org/t/solved-rate-limit-with-san-certificate-90-hostnames/4010/6 

  2. https://community.letsencrypt.org/t/beta-application-approval-time/1526/14 

  3. https://community.letsencrypt.org/t/using-the-webroot-domain-verification-method/1445/44