Guide: Set up open source SSL for nginx on Linux

HTTPS is the way to go for web apps these day’s. But the hassle of setting up, renewing, paying, … it can be a real pain. In comes Let’s Encrypt, a free, automated, and open certificate authority, provided by the Internet Security Research Group (ISRG). Housing board members/advisors from a range of big internet companies like Google and Mozilla.

What are we setting up?

In this guide we’ll be using certbot to automatically manage the needed SSL certificates, on the reverse proxy from our previous guide, for free. Making us able to server our entire web app through HTTPS.

1. Install certbot

$ sudo apt-get install python-certbot-nginx -t stretch-backports

2. Request certificate

SSH into the server you want to enable SSL on, in our case our reverse proxy server. Edit the nginx config file for your domain, in our case:

$ cd /etc/nginx/sites-available/
$ sudo nano default

http://www.example.com/.well-known is the location Let's Encrypt will be looking for the responses to their challenges. Add the lines marked in bold to direct requests to this url to the right path.

server {
listen 80;
listen [::]:80;
    server_name example.com www.example.com;

location /.well-known {
alias /var/www/example.com/.well-known;
}


# subsequent rules
}

Reload nginx

$ sudo systemctl reload nginx

Request a certificate using certbot

$ sudo certbot certonly --webroot -w /var/www/example.com/ -d example.com -d www.example.com

The requested files are put in

/etc/letsencrypt/live/example.com/

3. Configure nginx

Adjust your nginx configuration file, in our case /etc/nginx/sites-available/default

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_stapling on;
ssl_stapling_verify on;
    add_header Strict-Transport-Security "max-age=31536000";
    access_log /var/log/nginx/sub.log combined;
    location /.well-known {
alias /var/www/example.com/.well-known;
}
    location / {
# reverse proxy commands
}
}
Note — We’ve used the http2 protocol in the first two server config lines. It requires nginx version >= 1.9.5 if this is not the case you can replace http2 with http.

Test your nginx configuration and reload to enable the changes.

$ sudo nginx -t
$ sudo systemctl reload nginx

4. Auto renew your certificate

We’ll use a cronjob to make daily checks to renew certificates older than 60 days. Open /etc/crontab and add the following line:

20 4 * * * root certbot renew --quiet --renew-hook "systemctl reload nginx"

Every day at 04:20 cron will, as user root, tell certbot to renew all certificates older than 60 days and reload the nginx configuration when renewed.

To test if the renew will work, run this:

$ sudo certbot --dry-run renew 

To manually force a renewal, run this:

certbot renew --force-renew --renew-hook "systemctl nginx reload" 
Note — Be aware of the let’s encrypt renewal rate limits

5. Redirect HTTP to HTTPS (optional)

Add following server block before the current server block in your nginx configuration file, in our case /etc/nginx/sites-available/default

server {
listen 80;
listen [::]:80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

Test your nginx configuration and reload to enable the changes.

$ sudo nginx -t
$ sudo systemctl reload nginx

Done! When you navigate to https://www.example.com a secure connection will be established and (optionally) HTTP requests will be redirected to HTTPS.

domain secured