Setup HTTPS and HTTP/2 support on Ghost/Nginx/DO

Let's Encrypt just got stable from beta. Let's Encrypt is a free, automated, and open certificate authority brought to you by the non-profit Internet Security Research Group (ISRG).

Although they only offer certificates with 90 lifetimes, but hey it's trusted and zero cost!

Anyone who owns a domain can get a certificate validated for that domain at zero cost.

This guide is written for one-click Ghost installation instance on Digital Ocean, for automatically enable HTTPS on your website with EFF's Certbot, deploying Let's Encrypt certificates.

Checking requirement

$ apt-get update
$ apt-get install git

You need to use git later to install the client.

Check Nginx version.

$ nginx -v

Make sure it has nginx version: nginx/1.10.0 or later.

If you're using outdated version of Nginx, update it.

$ apt-get install nginx

Installing Certbot client

First, you need Certbot, previously the Let's Encrypt Client.

You have 2 options to get the client.

Getting the client from Eff.org

$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto

Getting the repo from Certbot Github

$ git clone https://github.com/certbot/certbot.git /opt/certbot/

I recommend you get it from Github and put it in /opt directory.

Preparing Nginx

In this guide, I'll display the demo of using the Certbot's webroot plugin. Let's make sure .well-known, the webroot directory is ready for validation from Let’s Encrypt validation server.

Add the following location block to inside the server block of your Nginx configuration, to ensure that files inside /.well-known/acme-challenge are served by the Nginx.

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

This is a useful and handy command to check if nginx configuration has any syntax error. Try to validate the configuration every time after you make changes.

$ nginx -t

Reload nginx, run nginx -s reload or service nginx reload.

$ nginx -s reload

Obtain an SSL Certificate

The following command will also install Python if not previously installed.

$ /opt/certbot/certbot-auto certonly -a webroot --webroot-path=/var/www/html -d jewei.com -d www.jewei.com

Here are some screens you might see.

In the above example, you'll find the certificates inside directory /etc/letsencrypt/live/jewei.com/.

Hardening security

You can build a more secure Diffie–Hellman key exchange for better security.

Let's generate a 2048-bit Diffie-Hellman Group.

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

The generation will take a few minutes, after that you will have a strong DG group at /etc/ssl/certs/dhparam.pem.

Adding the SSL Certificates to Nginx

Now you have the SSL certificate, you need to configure Nginx to use it.

Create an Nginx snippet at /etc/nginx/snippets/ssl-jewei.com.conf.

ssl_certificate /etc/letsencrypt/live/jewei.com/fullchain.pem; 
ssl_certificate_key /etc/letsencrypt/live/jewei.com/privkey.pem;

Create another snippet at /etc/nginx/snippets/ssl-params.conf.

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;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
ssl_dhparam /etc/ssl/certs/dhparam.pem;

The snippet above is taken from https://cipherli.st/ to provide Strong SSL Security for all modern browsers. They set a strong Forward Secrecy enabled ciphersuite.

Let's include the snippets to Nginx configuration like the example below.

server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;
  server_name jewei.com www.jewei.com;
  return 301 https://jewei.com$request_uri;
}

server {
  listen 443 ssl http2;
  server_name *.jewei.com;
  return 301 https://jewei.com$request_uri;
}

server {
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;
  include snippets/ssl-jewei.com.conf;
  include snippets/ssl-params.conf;

Now, reload or restart Nginx for it to take effects.

The Let's Encrypt TLS/SSL certificate should be now in place. Get yourself a cup of coffee, wait... read below first.

Verifying the changes

Run this command to see if http_v2_module is enabled.

$ nginx -V

If you're using Chrome browser, install HTTP/2 and SPDY indicator plugin so you can verify if you have the blue thunder icon like below.

Also notice the green https lock to the left of the domain in URL bar. Clicking the lock for more information can see the following details.

You can even check how strong your SSL doing with www.ssllabs.com. The following is a screenshot of part of the report. You can checkout the full report.

Automating renewal

Let's Encrypt certificates expired after 90 days, so it's logical to renew them automatically.

Create a config file under /etc/letencrypt/cli.ini.

# This is an example of the kind of things you can do in a configuration file.
# All flags used by the client can be configured here. Run Certbot with
# "--help" to learn more about the available options.

# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

# Uncomment and update to register with the specified e-mail address
email = [email protected]

# Uncomment and update to generate certificates for the specified
# domains.
domains = jewei.com, www.jewei.com

# Uncomment to use a text interface instead of ncurses
text = True

# Uncomment to use the webroot authenticator. Replace webroot-path with the
# path to the public_html / webroot folder being served by your web server.
authenticator = webroot
webroot-path = /var/www/html

Create a renewal script and put it in the cron, /etc/cron.daily/certbot.

Note it's in the daily cron as recommended by Certbot.

Note: if you're setting up a cron or systemd job, we recommend running it twice per day (it won't do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let's Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.

Yes they suggested it to run twice per day.

Here's a sample script.

#!/bin/sh

# re-new certs
/root/.local/share/letsencrypt/bin/letsencrypt  renew -c /etc/letsencrypt/cli.ini --quiet --no-self-upgrade

# reload nginx 
nginx -s reload

Now you should be able to leave it in peace.

References:

Setup HTTPS and HTTP/2 support on Ghost/Nginx/DO
Share this