Setting up Let's Encrypt SSL on Nginx

Let's say you have an nginx site that's proxying to a node.js backend, so your config looks like this:

server {
    listen 80;
    server_name app1.example.com

    location / {
        auth_basic "Restricted Access";       # Authentication realm
        auth_basic_user_file /etc/nginx/.htpasswd;  # Path to the password

    	proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}


Note that the app1.example.com should match the value in your server_name, and it is a valid DNS name.

Install certbot

You can use apt or snap on Ubuntu. I chose snap since it isolate the dependencies better:

sudo snap install --classic certbot

Run certbot

Backup a copy of your current nginx config, in case you need to revert it for any reason.

sudo certbot --nginx

When prompted, choose the domain defined above.

The certbot command will rewrite the nginx config to something like this:

server {
    server_name app1.example.com;

    location / {
        auth_basic "Restricted Access";       # Authentication realm
        auth_basic_user_file /etc/nginx/.htpasswd;  # Path to the password

    	proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/app1.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/app1.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = app1.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name app1.example.com;
    return 404; # managed by Certbot

}

Note how it adds an extra `server{..}` block for port 443 SSL, and has the port 80 server block redirect to port 443.

Validate the nginx config is correct via:

sudo nginx -t

Automatic certificate refreshing

  • Create a new file in /etc/cron.weekly : sudo touch /etc/cron.weekly/certbot

Make it executable: sudo chmod +x /etc/cron.weekly/certbot

And add this code:

#!/bin/sh
certbot renew

References

  1. How to use nginx as a reverse-proxy with letsencrypt
  2. How to Secure Nginx with Lets Encrypt on Ubuntu 20.04 with Certbot?