How to configure Nginx with Let’s Encrypt on Debian/Ubuntu Linux

How do I secure my Nginx web server with Let’s Encrypt free ssl certificate on my Ubuntu Linux 14.04/16.04 LTS or Debian Linux 8.x/9.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. This page shows 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 acme.sh client to secure Nginx with Let’s Encrypt on Debian

acme.sh 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 (use for existing server)
  • Standalone mode (no nginx installed)
  • Apache mode
  • Dns mode

Our sample setup to secure Nginx with Let’s Encrypt on Ubuntu

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

Step to configure and secure Nginx with Let’s Encrypt

The procedure is as follows to secure Nginx with Let’s Encrypt:

  1. Get acme.sh software to get SSL certificate:
    git clone https://github.com/Neilpang/acme.sh.git
  2. Create /.well-known/acme-challenge/ directory:
    mkdir -p /var/www/.well-known/acme-challenge/
  3. Obtaining an SSL certificate your domain:
    acme.sh --issue -w /DocumentRootPath/ -d your-domain
  4. Configure TLS/SSL on Nginx web server:
    vi /etc/nginx/sites-available/default
  5. Verify that auto-renewal cron job setup for your domain
  6. Open port 443 (HTTPS):
    ufw allow proto tcp from any to server-IP-here port 443

Install acme.sh

First, install the git and bc packages with apt-get command or apt command:
$ sudo apt-get install git bc wget curl
Sample outputs:

Fig.02: Install git and bc on Ubuntu/Debian Linux

Clone repo

Next, clone the acme.sh client, enter:
$ cd /tmp/
$ git clone https://github.com/Neilpang/acme.sh.git

Sample outputs:

Cloning into 'acme.sh'...
remote: Counting objects: 1578, done.
remote: Compressing objects: 100% (15/15), done.
remote: Total 1578 (delta 3), reused 0 (delta 0), pack-reused 1563
Receiving objects: 100% (1578/1578), 503.02 KiB | 0 bytes/s, done.
Resolving deltas: 100% (645/645), done.
Checking connectivity... done.

To install acme.sh client to your system, enter:
$ cd acme.sh/
$ sudo -i
# ./acme.sh --install

Sample outputs:

[Fri Sep  2 13:08:52 UTC 2016] Installing to /root/.acme.sh
[Fri Sep  2 13:08:52 UTC 2016] Installed to /root/.acme.sh/acme.sh
[Fri Sep  2 13:08:52 UTC 2016] OK, Close and reopen your terminal to start using acme.sh
[Fri Sep  2 13:08:52 UTC 2016] Installing cron job
no crontab for root
no crontab for root
[Fri Sep  2 13:08:53 UTC 2016] Good, bash is installed, change the shebang to use bash as prefered.
[Fri Sep  2 13:08:53 UTC 2016] OK

Make sure the following line added to your ~/.bashrc file:

. "$HOME/.acme.sh/acme.sh.env"

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

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

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

Type the following command (set D to actual DocumentRoot path as per your setup):
# D=/var/www/html
# mkdir -vp ${D}/.well-known/acme-challenge/
###---[ NOTE: Adjust permission as per your setup ]---###
# chown -R www-data:www-data ${D}/.well-known/acme-challenge/
# chmod -R 0555 ${D}/.well-known/acme-challenge/

Create directory to store SSL certicate

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

Generate your dhparams.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
OR use the following command to speed up dhparams generation:
# openssl dhparam -out dhparams.pem -dsaparam 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
acme.sh --issue -w /DocumentRootPath/ -d example.com
acme.sh --issue -w /DocumentRootPath/ -d www.bar.com -d bar.com
acme.sh --issue -w /path/to/www/htmlRoot/ -d example.com -k 2048

Where,

  1. --issue : Issue a new certificate.
  2. -w /DocumentRootPath/ : Specifies the web root folder for web root mode.
  3. -d example.com : Specifies a domain, used to issue, renew or revoke etc. Can be used multiple times.
  4. -k 2048 : Specifies the domain key length.

To issue a certificate for theos.in and www.theos.in, enter:
# acme.sh --issue -w /var/www/html -d theos.in -d 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
# acme.sh --issue -w /var/www/html -d theos.in -d www.theos.in -k 4096
Sample outputs:

Fig.03: 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 with http2 support ----#
    listen 74.86.26.69:443 http2;
    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:
# acme.sh --installcert -d theos.in --keypath /etc/nginx/ssl/theos.in/theos.in.key --fullchainpath /etc/nginx/ssl/theos.in/theos.in.cer --reloadcmd 'systemctl reload nginx'
Sample outputs:

[Fri Sep  2 15:19:56 UTC 2016] Installing key to:/etc/nginx/ssl/theos.in/theos.in.key
[Fri Sep  2 15:19:56 UTC 2016] Installing full chain to:/etc/nginx/ssl/theos.in/theos.in.cer
[Fri Sep  2 15:19:56 UTC 2016] Run Le_ReloadCmd: systemctl reload nginx
[Fri Sep  2 15:19:56 UTC 2016] Reload success

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

How do I renew a certificate?

Type the following command:
# acme.sh --renew -d theos.in
Sample outputs:

[Fri Sep  2 15:23:16 UTC 2016] Renew: 'theos.in'
[Fri Sep  2 15:23:16 UTC 2016] Skip, Next renewal time is: Mon Nov 21 15:07:55 UTC 2016
[Fri Sep  2 15:23:16 UTC 2016] Add '--force' to force to renew.

How do I upgrade acme.sh client?

Type the following command to upgrade acme.sh client to the latest code from https://github.com/Neilpang/acme.sh
# acme.sh --upgrade
Sample outputs:

[Sat Dec 24 17:22:50 UTC 2016] Installing from online archive.
[Sat Dec 24 17:22:50 UTC 2016] Downloading https://github.com/Neilpang/acme.sh/archive/master.tar.gz
[Sat Dec 24 17:22:55 UTC 2016] Extracting master.tar.gz
[Sat Dec 24 17:22:56 UTC 2016] Installing to /root/.acme.sh
[Sat Dec 24 17:22:56 UTC 2016] Installed to /root/.acme.sh/acme.sh
[Sat Dec 24 17:22:56 UTC 2016] Installing alias to '/root/.bashrc'
[Sat Dec 24 17:22:56 UTC 2016] OK, Close and reopen your terminal to start using acme.sh
[Sat Dec 24 17:22:56 UTC 2016] Good, bash is found, so change the shebang to use bash as preferred.
[Sat Dec 24 17:22:56 UTC 2016] OK
[Sat Dec 24 17:22:56 UTC 2016] Install success!
[Sat Dec 24 17:22:56 UTC 2016] Upgrade success!

A note about cron job

A cron job will try to do renewal a certificate for you too. This is installed by default as follows (no action required on your part):

0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
This entry is 1 of 5 in the Secure Web Server with Let’s Encrypt Tutorial series. Keep reading the rest of the series:

  1. How to configure Nginx with Let’s Encrypt on Debian/Ubuntu Linux
  2. How to secure Lighttpd with Let’s Encrypt certificate on Debian/Ubuntu
  3. How to secure Nginx with Let’s Encrypt certificate on Alpine Linux
  4. How to configure Nginx with Let’s Encrypt on CentOS 7

Published by SXI ADMIN