Create SSL Certificates

Create SSL Certificates

by John Vincent


Posted on August 9, 2018


This is part of a series of discussions regarding Deploying to a Digital Ocean Droplet. For more details, please see Overview of johnvincent.io website

Create SSL Certificates

SSL reference

Get SSL cert for:

  • johnvincent.io and www.johnvincent.io
  • music.johnvincent.io and www.music.johnvincent.io
  • mygithub.johnvincent.io and www.mygithub.johnvincent.io
  • rijksmuseum.johnvincent.io and www.rijksmuseum.johnvincent.io
  • internet-resources.johnvincent.io and www.internet-resources.johnvincent.io
  • peg-solitaire.johnvincent.io and www.peg-solitaire.johnvincent.io
  • omnifood.johnvincent.io and www.omnifood.johnvincent.io
  • images.johnvincent.io and www.images.johnvincent.io
  • jekyll.johnvincent.io and www.jekyll.johnvincent.io
  • linkedin.johnvincent.io and www.linkedin.johnvincent.io
  • test.johnvincent.io and www.test.johnvincent.io

Certificates are build by document root. As each domain has it’s own document root, there will be 5 sets of certificates.

Ensure all are forwarding to the correct ip.

Install letsencrypt

sudo apt-get update
sudo apt-get install letsencrypt

Obtain an SSL Certificate

We'll show you how to use the Webroot plugin to obtain an SSL certificate.

How Webroot Plugin Works

The Webroot plugin works by placing a special file in the /.well-known directory within your document root, which can be opened (through your web server) by the Let's Encrypt service for validation. Depending on your configuration, you may need to explicitly allow access to the /.well-known directory.

sudo vi /etc/nginx/sites-available/default

Note root directive, this is webroot-path

root /var/www/html;

After location block, add:

location ~ /.well-known {
                allow all;
        }

Check your configuration for syntax errors:

sudo nginx -t
If no errors are found, restart Nginx with this command:
sudo systemctl restart nginx

Now that we know our webroot-path, we can use the Webroot plugin to request an SSL certificate with these commands. Here, we are also specifying our domain names with the -d option. If you want a single cert to work with multiple domain names (e.g. example.com and www.example.com), be sure to include all of them. Also, make sure that you replace the highlighted parts with the appropriate webroot path and domain name(s):

email address:

Should see:
IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to jv@johnvincent.io.
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/johnvincent.io/fullchain.pem. Your
   cert will expire on 2017-05-31. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.

Files are in:
/etc/letsencrypt/archive/johnvincent.io

Files are:
cert1.pem, chain1.pem, fullchain1.pem, privkey1.pem

However, Let's Encrypt creates symbolic links to the most recent certificate files in the /etc/letsencrypt/live/your_domain_name directory. Because the links will always point to the most recent certificate files, this is the path that you should use to refer to your certificate files.

see:
/etc/letsencrypt/live/johnvincent.io

Script file

Create script file ~/bin/encrypt-ssl

#!/bin/sh
#
#  script to create or renew SSL certs
#
domain_encrypt() (
	echo "****************************************************"
  echo "**** Encrypt domain www.johnvincent.io";
	echo "****************************************************"
  sudo letsencrypt certonly -a \
    webroot --webroot-path=/var/www/johnvincent.io/html \
    -d johnvincent.io \
    -d www.johnvincent.io;
)
#
subdomain_encrypt() (
  FILE="$1";
  if [ -z "$FILE" ]; then
    return;
  fi;
	echo "****************************************************"
  echo "**** Encrypt subdomain $FILE";
	echo "****************************************************"
  sudo letsencrypt certonly -a \
    webroot --webroot-path=/var/www/$FILE/html \
    -d $FILE.johnvincent.io \
    -d www.$FILE.johnvincent.io;
)
cd
#
echo "Create or renew SSL certificates"
#
domain_encrypt
#
subdomain_encrypt jekyll
subdomain_encrypt images
subdomain_encrypt music
subdomain_encrypt mygithub

subdomain_encrypt rijksmuseum
subdomain_encrypt internet-resources

subdomain_encrypt peg-solitaire
subdomain_encrypt omnifood

subdomain_encrypt linkedin
subdomain_encrypt test

echo "Restarting Nginx"
nginx-restart
#
echo "Completed"

Add SSL for Domain and Subdomains

encrypt-ssl`

Generate Strong Diffie-Hellman Group

To further increase security, you should also generate a strong Diffie-Hellman group. To generate a 2048-bit group, use this command:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

This may take a few minutes but when it's done you will have a strong DH group at

/etc/ssl/certs/dhparam.pem

Configure TLS/SSL on Web Server (Nginx)

Now that you have an SSL certificate, you need to configure your Nginx web server to use it.

Create a Configuration Snippet Pointing to the SSL Key and Certificate

First, let's create a new Nginx configuration snippet in the /etc/nginx/snippets directory. This is done for each domain and subdomain.

sudo vi /etc/nginx/snippets/ssl-johnvincent.io.conf
add:
ssl_certificate /etc/letsencrypt/live/johnvincent.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/johnvincent.io/privkey.pem;
sudo vi /etc/nginx/snippets/ssl-music-johnvincent.io.conf
add:
ssl_certificate /etc/letsencrypt/live/music.johnvincent.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/music.johnvincent.io/privkey.pem;

and repeat for all subdomains.

Create a Configuration Snippet with Strong Encryption Settings

The parameters we will set can be reused in future Nginx configurations, so we will give the file a generic name:

sudo vi /etc/nginx/snippets/ssl-params.conf
add:
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
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;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Adjust the Nginx Configuration to Use SSL

Now that we have our snippets, we can adjust our Nginx configuration to enable SSL.

Adjust the Firewall

Check if SSL enabled:

sudo ufw status

To additionally let in HTTPS traffic, we can allow the "Nginx Full" profile and then delete the redundant "Nginx HTTP" profile allowance:

sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

sudo ufw status

Set Up SSL Certificates Auto Renewal

To trigger the renewal process for all installed domains, run this command:

cd
cd tmp (just in case)
sudo letsencrypt renew