Oct 5, 2023 6 min read

Secure Nginx with Let's Encrypt on CentOS 7

Secure Nginx with Let's Encrypt on CentOS 7 with our step-by-step tutorial. Let's Encrypt certificates are now trusted by nearly all browsers.

Secure Nginx with Let's Encrypt on CentOS 7
Table of Contents

Introduction

Before we begin talking about how to Secure Nginx with Let's Encrypt on CentOS 7, let's briefly understand – What is Let's Encrypt?

The Internet Security Research Group, a free and open certificate authority (ISRG) created Let's Encrypt. Let's Encrypt certificates are now trusted by nearly all browsers.

Let's Encrypt is a non-profit certificate authority that provides free SSL/TLS certificates, ensuring secure communication between a website and its visitors. These certificates encrypt data transmitted over the internet, safeguarding against unauthorized access. Let's Encrypt stands out for its automated certificate issuance and renewal process, making it easy for website owners to implement and maintain secure connections.

In this tutorial, you will Secure Nginx with Let's Encrypt on CentOS 7. We will also address a few FAQs on how to Secure Nginx with Let's Encrypt on CentOS 7.

Prerequisites

Before proceeding with this tutorial, please ensure that you have met the following prerequisites:

  • You have a domain name that directs people to the public server's IP address. In this tutorial, we will use the website example.com.
  • You enabled the EPEL repository and installed Nginx by following the instructions.

Install Certbot

Certbot is a simple tool for obtaining and renewing Let's Encrypt SSL certificates, as well as configuring web servers.

Run the following command to install the certbot package from the EPEL repository:

sudo yum install certbot

Generate Strong Dh (Diffie-Hellman) Group

The Diffie-Hellman key exchange (DH) method secures the exchange of cryptographic keys over an unsecured communication channel.

Type the following command to generate a new set of 2048 bit DH parameters:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
💡
You can increase the size to 4096 bits if you want, but the generation may take longer than 30 minutes depending on the system entropy.

Obtaining a Let’s Encrypt SSL certificate

To obtain an SSL certificate for our domain, we'll use the Webroot plugin, which works by creating a temporary file in the $webroot-path/.well-known/acme-challenge directory for validating the requested domain. Let's Encrypt makes HTTP requests to the temporary file to ensure that the requested domain resolves to the server where certbot is running.

To simplify things, we'll map all HTTP requests for .well-known/acme-challenge to a single directory, /var/lib/letsencrypt.

The commands below will create the directory and make it writable by the Nginx server.

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

To avoid code duplication, create the following two snippets, which will be included in all of our Nginx server block files:

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

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

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
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=15768000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

The above snippet includes Mozilla's recommended chippers, enables OCSP Stapling, HTTP Strict Transport Security (HSTS), and enforces a few security-focused HTTP headers.

After you've created the snippets, open the domain server block and include the letsencrypt.conf snippet as shown below:

server {
  listen 80;
  server_name example.com www.example.com;

  include snippets/letsencrypt.conf;
}

Reload the Nginx configuration for changes to take effect:

sudo systemctl reload nginx

You can now use Certbot with the webroot plugin to obtain your domain's SSL certificate files by issuing:

sudo certbot certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com

If the SSL certificate is successfully obtained, certbot will print the following message:

Output

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2018-06-11. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. 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

Now that you have the certificate files, you can edit your domain server blocks as follows:

Output

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;

    # . . . other code
}

With the above configuration, we force HTTPS and redirect the www to the non-www version.

Finally, restart the Nginx service to see the changes take effect:

sudo systemctl reload nginx

Auto-renewing Let’s Encrypt SSL certificate

The certificates issued by Let's Encrypt are valid for 90 days. To automatically renew the certificates before they expire, we will set up a cronjob to run twice a day and renew any certificate 30 days before it expires.

To create a new cronjob, use the crontab command:

sudo crontab -e

Paste the following lines:

0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "systemctl reload nginx"

Save and exit the file.

To test the renewal process, run the certbot command with the --dry-run switch:

sudo certbot renew --dry-run

The test renewal process was successful if there are no mistakes.

FAQs to Secure Nginx with Let's Encrypt on CentOS 7

Why should I secure Nginx with Let's Encrypt?

Securing Nginx with Let's Encrypt ensures encrypted data transmission, enhances website security, and builds trust with visitors.

How can I obtain an SSL/TLS certificate from Let's Encrypt? 

Use Certbot's Nginx plugin to obtain and automatically install a certificate using the command certbot --nginx.

Where are the Let's Encrypt certificates stored on CentOS 7? 

Let's Encrypt certificates are stored in the directory /etc/letsencrypt/live/yourdomain.com/.

How can I configure Nginx to use Let's Encrypt certificates? 

Update your Nginx server block configuration to point to the Let's Encrypt certificates and enable HTTPS.

How do I automate the renewal of Let's Encrypt certificates on CentOS 7?

 Certbot automatically sets up a cron job to renew certificates. No additional steps are required for automation.

What happens if my Let's Encrypt certificate expires? 

When a certificate expires, visitors will see a security warning. To avoid this, ensure regular certificate renewal with Certbot's automated process or manual intervention.

How can I automatically renew Let's Encrypt certificates? 

Certbot automatically creates a cron job during installation to renew certificates. You don't need to do anything extra.

Conclusion

In this tutorial, you downloaded SSL certificates for your domain using the Let's Encrypt client, certbot. You've also created Nginx snippets to avoid code duplication and set up Nginx to use the certificates. At the end of the tutorial, you set up a cronjob to renew your certificates automatically.

If you want to learn more about Certbot, go through their documentation.

If you have any queries, please leave a comment below and we’ll be happy to respond to them.

Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to DevOps Blog - VegaStack.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.