How to Secure Nginx with Let’s Encrypt on Ubuntu 20.04

Secure Nginx with Let's Encrypt on Ubuntu 20.04

In this article, we will have explained the necessary steps to secure Nginx with let’s encrypt on Ubuntu 20.04 LTS. Before continuing with this tutorial, make sure you are logged in as a user with sudo privileges. All the commands in this tutorial should be run as a non-root user.

Let’s Encrypt is a free, automated, and open certificate authority developed by the Internet Security Research Group (ISRG) that provides free SSL certificates. Let’s Encrypt uses client software (certbot) that automates the process of certificate creation, validation, signing, implementation, and renewal of certificates.

Secure Nginx with Let’s Encrypt on Ubuntu 20.04

Step 1. First, before you start installing any package on your Ubuntu server, we always recommend making sure that all system packages are updated.

sudo apt update
sudo apt upgrade

Note: Before install the Let’s Encrypt SSL domain should be well accessed and use the Nginx virtual host. Read the tutorial on how to install Nginx on Ubuntu.

Step 2. Install Certbot.

Certbot is a fully-featured and easy to use tool that automates the tasks for obtaining and renewing Let’s Encrypt SSL certificates and configuring web servers to use the certificates. To install it run the following commands:

sudo apt install certbot

After that, Generate a new set of 2048 bit DH parameters by typing the following command:

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

The Let’s Encrypt server makes HTTP requests to the temporary file to verify that the requested domain resolves to the server where certbot runs. To make it more simple we’re going to map all HTTP requests for .well-known/acme-challenge to a single directory, /var/lib/letsencrypt:

sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp www-data /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt

Then, create the following two snippets which will be included in all Nginx server block files:

sudo nano /etc/nginx/snippets/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}

Next, create the second snippet, ssl.conf:

sudo nano /etc/nginx/snippets/ssl.conf
ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

Next, open the domain server block file and include the letsencrypt.conf:

sudo nano /etc/nginx/sites-available/example.com.conf
server {
  listen 80;
  server_name example.com www.example.com;

  include snippets/letsencrypt.conf;
}

Don’t forget to create a symbolic link from the file to the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/
sudo systemctl restart nginx

Once done, run Certbot with the webroot plugin and obtain the SSL certificate files by issuing:

sudo certbot certonly --agree-tos --email admin@example.com --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com

Finally, steps, edit your domain server block as follows:

sudo nano /etc/nginx/sites-available/example.com.conf
server {
    listen 80;
    server_name www.example.com example.com;

    include snippets/letsencrypt.conf;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301 https://example.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;
}

Reload the Nginx service for changes to take effect:

sudo systemctl reload nginx

Step 3. Checking your Certificate Status.

You can ensure that Certbot created your SSL certificate correctly by using the SSL Server Test from the cloud security company Qualys. Open the following link in your preferred web browser, replacing your-domain.com with your base domain:

https://www.ssllabs.com/ssltest/analyze.html?d=your-domain.com

Step 4. Renew Let’s Encrypt SSL Certificate

And finally, test automatic renewal:

sudo certbot renew --dry-run

That’s all you need to do to install SSL Let’s Encrypt with Nginx on Ubuntu 20.04 Focal Fossa. I hope you find this quick tip helpful. If you have questions or suggestions, feel free to leave a comment below.