How to secure Nginx with Let’s Encrypt on CentOS 7

Let’s Encrypt is a free and open source certificate authority developed by Let’s Encrypt Internet Security Research Group(ISRG). Certificates issued by Let’s Encrypt are trusted by almost all browsers today.

In this tutorial, we will provide step by step instructions on how to secure your Nginx with Let’s Encrypt using certbot tool on CentOS 7.


Make sure you meet the following prerequisites before proceeding with this tutorial:

  • You have a domain name that points to your public server’s IP address. In this tutorial we will use domains
  • Activate the EPEL repository and install Nginx by following the tutorial How to Install Nginx on CentOS 7.

Install Certbot

Certbot is a full-featured, easy-to-use tool that can automate the task of obtaining and renewing Let’s Encrypt SSL Certificates. Certbot will also manage all web server configurations so they can use the certificate directly.

To install the certbot package from the EPEL repository, run the following command:

sudo yum install certbot

Create a Dh key exchange certificate (Diffie-Hellman)

Diffie-Hellman (DH) key exchange is a method of exchanging secure cryptographic keys over an insecure communication channel. We will create a new 2048-bit DH parameter to enhance security:

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

If you are still paranoid, you can change the size up to 4096 bits, but in this case, the release may take more than 30 minutes depending on the processing capabilities of your system.

Obtained Let’s Encrypt SSL certificate

To get the SSL certificate for the domain we will use the Webroot plugin which works by creating a temporary file to validate the required domain in the directory ${webroot-path}/.well-known/acme-challenge.

Let’s Encrypt server makes HTTP requests for temporary files to verify that the requested domain has completed data requests to the server where certbot is running.

See also  How to install Visual Studio Code on CentOS 8

To keep it simple, we will set all HTTP requests to .well-known/acme-challengeto a single directory, /var/lib/letsencrypt.

The following command will create a 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 we will include in all Nginx server block files.

Open your text editor and create an excerpt letsencrypt.conf:

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

Create the snippets ssl.conf Which includes the Mozilla-recommended profiler, enables OCSP Stapling, HTTP Strict Transport Security (HSTS) and enforces some security-focused HTTP headers.

sudo nano /etc/nginx/snippets/ssl.conf
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_prefer_server_ciphers on;

ssl_stapling on;
ssl_stapling_verify on;
resolver 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;

Once the snippets are generated, go to the domain server block and include the snippets letsencrypt.conf As shown below:

server {
  listen 80;

  include snippets/letsencrypt.conf;

Restart the Nginx service for the changes to take effect:

sudo systemctl reload nginx

Now you can run Certbot using the webroot plugin and get the SSL certificate file by typing the command:

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

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

 - Congratulations! Your certificate and chain have been saved at:
   Your key file has been saved at:
   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:
   Donating to EFF:          

Now that you have the certificate file, you can edit your domain server block as follows:

server {
    listen 80;

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

server {
    listen 443 ssl http2;

    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;
    ssl_trusted_certificate /etc/letsencrypt/live/;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301$request_uri;

server {
    listen 443 ssl http2;

    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;
    ssl_trusted_certificate /etc/letsencrypt/live/;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # . . . other code

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

See also  How to install and configure Skype on CentOS 8

Restart the Nginx service for the changes to take effect:

sudo systemctl reload nginx

How to auto-renew Let’s encrypt SSL certificates

Let’s Encrypt certificates are valid for 90 days. To automatically renew certificates before they expire, the certbot package creates a cronjob that runs twice a day and will automatically renew any certificate within 30 days before the certificate expires.

Run command crontab To create a new cronjob:

sudo crontab -e

Copy and paste the following line:

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 close the file.

To test the update process, you can use the certbot command followed by a statement --dry-run :

sudo certbot renew --dry-run

If there are no errors, the test update was successful.


In this tutorial, you can use the Let’s Encrypt client, certbot, to download an SSL certificate for your domain. I also created Nginx snippets to avoid code duplication and set Nginx to use certificates. At the end of the tutorial, I set up a cronjob to automatically renew the certificate.

Source link