How to Secure Nginx with Letsencrypt on Ubuntu 20.04/22.04

Let’s Encrypt is a certificate authority (CA) that provides free certificates for Transport Layer Security (TLS) encryption. It simplifies the process of creation, validation, signing, installation, and renewal of certificates by providing a software client - Certbot.

It was developed by the Internet Security Research Group (ISRG) and trusted by all major browsers. It is used to automate the process of certificate creation, validation, signing, implementation, and renewal of certificates for secure websites.

The certificate is valid for only 90 days, so you will need to renew it manually or or set up the auto renewal system,

Let’s encrypt supports automated certification issuance for Apache, Nginx, Plex, and HAproxy. We will cover nginx in this guide.

Prerequisites

  • An Ubuntu 20.04 server with internet access and public IP
  • A valid domain name with DNS pointed to the server
  • Root access or sudo access to the server

Installing the Certbot Let’s Encrypt Client

Log in to the server using ssh user@server -p port:

1
ssh ubuntu@10.2.10.10

Update all of your packages to their latest available versions.

1
2
sudo apt update
sudo apt upgrade -y

Install Nginx

1
sudo apt install -y nginx

Start and enable nginx

1
2
systemctl start nginx
systemctl enable nginx

Let’s create nginx config for site1.citizix.com:

Open the configuration file with your text editor:

1
sudo vim /etc/nginx/conf.d/site1.conf

Add this content:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server {
    listen 80;
    server_tokens off;
    client_max_body_size 10M;
    server_name site1.citizix.com;

    access_log /var/log/nginx/site1.citizix.com/access.log;
    error_log /var/log/nginx/site1.citizix.com/error.log;
    ignore_invalid_headers off;

    ## Deny illegal Host headers
    if ($host !~* ^(site1.citizix.com)$ ) {
        return 444;
    }

    root /var/www/site1.citizix.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Scheme $scheme;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

}

Install the Certbot Client

The Certbot is a command-line tool used to simplifies the process for obtaining and renewing Let’s Encrypt SSL certificates for your website. Use this command to install it along with python dependencies:

1
sudo apt install certbot python3-certbot-nginx

if you have ufw firewall installed and enabled, open up http and https traffic from the web:

1
2
3
ufw allow 80
ufw allow 443
ufw reload

Obtaining a Certificate

Stop nginx:

1
sudo systemctl stop nginx
1
sudo certbot --nginx --non-interactive --agree-tos --email admin@citizix.com -d site1.citizix.com

Output

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ sudo certbot --nginx --non-interactive --agree-tos --email admin@citizix.com -d site1.citizix.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Account registered.
Requesting a certificate for site1.citizix.com
Performing the following challenges:
http-01 challenge for site1.citizix.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/site1.citizix.com.conf
Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/site1.citizix.com.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled
https://site1.citizix.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/site1.citizix.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/site1.citizix.com/privkey.pem
   Your certificate will expire on 2021-11-05. To obtain a new or
   tweaked version of this certificate in the future, simply run
   certbot again with the "certonly" option. To non-interactively
   renew *all* of your certificates, run "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Start nginx:

1
sudo systemctl start nginx

Update Nginx config to redirect http traffic to https

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
server {
    server_tokens off;
    client_max_body_size 10M;
    server_name site1.citizix.com;

    access_log /var/log/nginx/site1.citizix.com/access.log;
    error_log /var/log/nginx/site1.citizix.com/error.log;
    ignore_invalid_headers off;

    ## Deny illegal Host headers
    if ($host !~* ^(site1.citizix.com)$ ) {
        return 444;
    }

    root /var/www/site1.citizix.com;

    location / {
        proxy_pass http://127.0.0.1:8096;
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Scheme $scheme;
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/site1.citizix.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/site1.citizix.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 = site1.citizix.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen 80;
    server_name site1.citizix.com;
    return 404; # managed by Certbot
}

Enabling Auto renew on Letsencrypt

To enable auto renew on the certificates we just created, add a cron that will check periodically if there is any certificate that is almost due.

In my case, I will create a cron to run every 03:07 hrs everyday to perform action since that is when there is less traffic on my site.

Use this command to edit cron:

1
crontab -e

Then add this command to run every 03:07 hrs

1
07 03 * * * /usr/bin/certbot renew --quiet

Save the file. You can confirm using this command:

1
2
3
# crontab -l

07 03 * * * /usr/bin/certbot renew --quiet
comments powered by Disqus
Citizix Ltd
Built with Hugo
Theme Stack designed by Jimmy