<- Back to writeups

Let's Encrypt Guide

No Reason Why Not HTTPS

HTTPS is of course one of the most basic cornerstones of a secure website, whether it handles user data or serves static content.

It doesn't matter how secure the site itself is if it lacks this basic component. Sure you prevent XSS and SQLi, but the world can see the password your user submits. Whatever selection and options they make, the resource they request (URI), and their session cookie are plain to see. Even if you're serving static content, someone may intercept the connection and manipulate your site (man in the middle), and the visitor would see the altered site. HTTPS ensures no one else sees what the user submits, no one else sees what the user looks at, and that the user receives the real website.

Of course, HTTPS doesn't protect users if the website is inherently vulnerable. SSL/TLS also isn't without faults that allows attackers to decrypt or redirect the traffic. Despite it's shortcomings, it's far better than nothing.

It's easy to get started with Let's Encrypt, which provides free certificates. Below shows you how to set it up.

Get the client

Download the Let's Encrypt official client, certbot, from its git repository.

sudo git clone https://github.com/certbot/certbot.git /opt/certbot
cd /opt/certbot

Get certificate

One of the methods Let's Encrypt confirms domain ownership is via a challenge, basically a file with a long random name. It's placed in your website's root directory and Let's Encrypt attempts to access it via $HOSTNAME.com/challenge and verify your ownership of $HOSTNAME. Launch the client and obtain a certificate using this method.

sudo ./certbot-auto certonly --webroot -w /var/www/$YOUR_DIR/ -d $HOSTNAME.com -d www.$HOSTNAME.com

Add other roots and subdomains as necessary using -w and -d.

Certbot will go through the set up process automatically and you'll receive a new certificate. For the first time, some information will be prompted such as email address.

To view active certificates, tree the cert directory.

tree /etc/letsencrypt/live/

A Diffie-Hellman group also needs to get generated.

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

Set up server configs

Change the SSL settings in Nginx's config file at /etc/nginx/nginx.conf.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;

Change the server block in /etc/nginx/sites-enabled/ to use SSL/TLS. The below example uses relatively strong settings.

listen 443 ssl default_server;

# SSL/TLS stuff
ssl_certificate /etc/letsencrypt/live/$HOSTNAME.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$HOSTNAME.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/$HOSTNAME.com/fullchain.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_timeout 1d;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

Create an additional server block to redirect regular HTTP requests to HTTPS.

server {
    listen 80;
    server_name $HOSTNAME.com www.$HOSTNAME.com;
    return 301 https://$host$request_uri;


The assigned certificate will inevitably expire. Note that Let's Encrypt will remind you via email if it's expiring soon. Certbot can easily renew certs.

cd /opt/certbot
sudo ./certbot-auto renew --force-renewal --pre-hook "service nginx stop" --post-hook "service nginx start"

<- Back to writeups