≡ Menu

How to configure Nginx with free Let’s Encrypt SSL certificate on Debian or Ubuntu Linux

How do I secure my Nginx web server with Let’s Encrypt free ssl certificate on my Ubuntu Linux 14.04 LTS or Debian Linux 8.x server?

Let’s Encrypt is a free, automated, and open certificate authority for your website or any other projects. You can grab free TLS/SSL certificate including wildcard certificate to create encrypted HTTPS session for your site visitors. In this tutorial, I will explain how to use Let’s Encrypt to install a free SSL certificate for Nginx web server along with how to properly deploy Diffie-Hellman on your nginx server to get SSL labs A+ score.

Say hello to Le client

le.sh (“le”) is a shell script client for LetsEncrypt free Certificate. It is very easy to use and works great with both Apache and Nginx. It works in the following mode:

  • Webroot mode
  • Standalone mode
  • Apache mode
  • Dns mode

Please note that LetsEncrypt certificates are only valid for 90 days. Automatic renewal functionality is a bit tricky and need to be done via cron job. The official nginx installer is not yet functional.

Our sample setup

Fig.01: Our sample Nginx TLS/SSL Security with Let's Encrypt on Ubuntu Linux

Fig.01: Our sample Nginx TLS/SSL Security with Let’s Encrypt on Ubuntu Linux

  1. Default Nginx config file : /etc/nginx/sites-available/default
  2. Nginx SSL certification directory : /etc/nginx/ssl/theos.in/
  3. Nginx DocumentRoot (root) path : /var/www/html/
  4. Nginx TLS/SSL Port: 443
  5. Our sample domain: theos.in
  6. Dedicated public IP: 74.86.26.69

Install le

First, install the git and bc packages with apt-get command:
$ sudo apt-get install git bc
Next, clone the le client, enter:
$ cd /tmp/
$ git clone https://github.com/Neilpang/le.git

Sample outputs:

Cloning into 'le'...
remote: Counting objects: 641, done.
remote: Compressing objects: 100% (79/79), done.
remote: Total 641 (delta 40), reused 0 (delta 0), pack-reused 562
Receiving objects: 100% (641/641), 144.22 KiB | 0 bytes/s, done.
Resolving deltas: 100% (236/236), done.
Checking connectivity... done.

To install le.sh to your system, enter:
$ cd le
$ sudo ./le.sh install

After install, you must close current terminal and reopen again to make the alias take effect. Or simply type the following command:
$ source ~/.bashrc
Test it (first become root user):
$ sudo -s
# le

All of the following command issues as root user i.e. type the following command first:
$ sudo -s

Create /.well-known/acme-challenge/ directory

Type the following command:
# mkdir -p /var/www/html/.well-known/acme-challenge/
###---[ NOTE: Adjust permission as per your setup ]---###
# chown -R www-data:www-data /var/www/html/.well-known/acme-challenge/
# chmod -R 0444 /var/www/html/.well-known/acme-challenge/

Create directory to store SSL certicate

# mkdir -p /etc/nginx/ssl/theos.in/

Generate your dhparam.pem file

You need to use a strong Diffie-Hellman (DH) group, regardless of the server software you use. The simplest way of generating a new group is to use OpenSSL. Type the following command to create the dhparam.pem file:
# cd /etc/nginx/ssl/theos.in/
I suggest that you generate a 4096-bit group:
# openssl dhparam -out dhparams.pem 4096
Sample outputs:

Generating DH parameters, 4096 bit long safe prime, generator 2
This is going to take a long time
...............................................................+.........+.................................................................................................................................................................................+.............+......................................................................................................................................
..
.............................................................................................................+...................................................................................+.........+.......................................................................................................................................................................++*++*

Issue a certificate for theos.in domain

The syntax is as follows
le issue /DocumentRootPath/ example.com
le issue /DocumentRootPath/ example.com www.foo.com,bar.com
le issue /DocumentRootPath/ example.com 2048

To issue a certificate for theos.in and www.theos.in, enter:
# le issue /var/www/html theos.in www.theos.in
For example, if you give “no” to “key-length”, it will use default length 2048. In this example set “key-length” to 4096
# le issue /var/www/html theos.in www.theos.in 4096
Sample outputs:

Fig.02: Issue a certificate

Fig.02: Issue a certificate

Configure TLS/SSL on Nginx web Server

Edit nginx.conf or /etc/nginx/sites-available/default as follows:
# vi /etc/nginx/sites-available/default
Add the following configuration directives

## START: SSL/HTTPS theos.in ###
server {
    #------- Start SSL config ----##
    listen 74.86.26.69:443;
    server_name theos.in;
    ssl on;
    ssl_certificate /etc/nginx/ssl/theos.in/theos.in.cer;
    ssl_certificate_key /etc/nginx/ssl/theos.in/theos.in.key;
    ssl_session_timeout 30m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
    ssl_session_cache shared:SSL:10m;
    ssl_dhparam /etc/nginx/ssl/theos.in/dhparams.pem;
    ssl_prefer_server_ciphers on;
 
    ## Improves TTFB by using a smaller SSL buffer than the nginx default
    ssl_buffer_size 8k;
 
    ## Enables OCSP stapling
    ssl_stapling on;
    resolver 8.8.8.8;
    ssl_stapling_verify on;
 
    ## Send header to tell the browser to prefer https to http traffic
    add_header Strict-Transport-Security max-age=31536000;
 
    ## SSL logs ##
    access_log /var/log/nginx/theos.in/ssl_access.log;
    error_log /var/log/nginx/theos.in/ssl_error.log;
    #-------- END SSL config -------##
 
    # Add rest of your config below like document path and more ##
}
## END SSL theos.in ######

Save and close the file.

Install the issued certificate to Nginx web server

Type the following command:
# le installcert theos.in /etc/nginx/ssl/theos.in/theos.in.cer /etc/nginx/ssl/theos.in/theos.in.key /etc/nginx/ssl/theos.in/ca.cer 'service nginx reload'
To avoid chaining issue, enter:
# cd /etc/nginx/ssl/theos.in/
# cat theos.in.cer ca.cer > foo
# mv foo theos.in.cer
# service nginx reload

Open port 443

Type the following ufw command:
# ufw allow proto tcp from any to 74.86.26.69 port 443

Test it

Type the following url:
https://theos.in
Or visit SSL labs to test your TLS/SSL config:

Fig.03: SSL Labs A+ score

Fig.03: SSL Labs A+ score

How do I renew a certificate?

Type the following command:
# le renew theos.in
Sample outputs:

Skip, Next renewal time is: Sat May 21 20:45:17 UTC 2016

A cron job will try to do renewal a certificate for you too:

0 0 * * * LE_WORKING_DIR="/root/.le" "/root/.le"/le.sh cron > /dev/null
Share this tutorial on:
{ 7 comments… add one }
  • ling March 10, 2016, 7:27 am

    Another dream comes true.
    I was hoping such a tool for a long time, good for our wallets.
    Thanks (the procedure worked fine for me).

  • Washington March 10, 2016, 5:54 pm

    Hi, I followed the steps in this guide till I got unable to load Private Key, after I run:

    le issue /usr/share/nginx/html themain.com www.thedomain.com,other.thedomain.com 4096
    Outputs:

    unable to load Private Key
    139662025688736:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
    printf: usage: printf [-v var] format [arguments]
    unable to load Private Key
    139831152248480:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
    printf: usage: printf [-v var] format [arguments]
    unable to load key file
    140545094272672:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:703:Expecting: ANY PRIVATE KEY
    Register account Error.
  • pixel March 10, 2016, 6:06 pm

    I follow your blog since about a year, but I want to thank you today for this great howto. I didn’t even knew the existence of let’s encrypt, this is a great service and you write a great guide to use it. Thank you :)

  • Tom March 10, 2016, 7:01 pm

    Thanks. It is working for me. But, why do I need to create /.well-known/acme-challenge/ directory in /home/mydomain/ ? What is the purpose of the /.well-known/acme-challenge/ ?

  • Istimsak March 14, 2016, 3:48 pm

    Interesting howto article. If you don’t mind me asking, what inspired you to write this howto, what did you see in “lets encrypt” that made you share such valuable information?

  • facio April 7, 2016, 10:31 am

    It’s better to do:
    chmod -R 0555 /var/www/html/.well-known/acme-challenge/
    instead of
    chmod -R 0444 /var/www/html/.well-known/acme-challenge/
    because chmod 0444 will fail domain validation.

Security: Are you a robot or human?

Leave a Comment

You can use these HTML tags and attributes: <strong> <em> <pre> <code> <a href="" title="">


   Tagged with: