Securing Nginx with Let's Encrypt SSL on CentOS 7

Let's Encrypt is a free, automated, and open Certificate Authority (CA) provided by the Internet Security Reseacrh Group (ISRG). It allows website owners to obtain trusted SSL certificates that are recognized by all major modern browsers. This guide demonstrates how to use the Certbot tool to generate and manage SSL certificates for Nginx on a CentOS 7 system.

Requirements

Before proceeding, ensure the following prerequisites are met:

  • A registered domain name pointing to your server's public IP address. In this guide, we use example.com as a placeholder.
  • Nginx installed on your CentOS 7 server with the EPEL repository enabled.
  • Root or sudo privileges.

Step 1: Install Certbot

Certbot is a versatile utility designed to automate the process of obtaining and renewing SSL certificates. You can install it directly from the EPEL repository using the YUM package manager:

sudo yum install certbot

Step 2: Generate Diffie-Hellman Parameters

Diffie–Hellman (DH) key exchange is a method that allows two parties to establish a shared secret over an insecure channel. Enhancing your server's security with a strong DH group is a recommended best practice.

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

Note: Generating a 2048-bit parameter usually takes a few minutes. You may use 4096 bits for higher security, though it will take significantly longer to generate depending on the system's entropy.

Step 3: Prepare the Webroot Directory

To validate domain ownership, Certbot's Webroot plugin creates a temporary file in the .well-known/acme-challenge directory of you're webroot. The Let's Encrypt server then makes an HTTP request to retrieve this file. We will centralize thece requests into a specific directory.

Create the directory and set the necessary permissions for Nginx:

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

Step 4: Configure Nginx Snippets

To maintain clean configuration files and avoid redundancy, we will create modular snippets that can be included in any Nginx server block.

First, create the snippets directory:

sudo mkdir /etc/nginx/snippets

Create the first snippet, acme-challenge.conf, to handle the validation requests:

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

Create the second snippet, ssl-params.conf, to define secure SSL settings based on modern standards (including HSTS and OCSP Stapling):

ssl_dhparam /etc/ssl/certs/dhparam.pem;

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
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=63072000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

Step 5: Apply Configuration and Generate Certificate

Modify your domain's server block to include the ACME challenge snippet. For example, edit /etc/nginx/conf.d/example.com.conf:

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

    include snippets/acme-challenge.conf;
}

Reload Nginx to apply the changes:

sudo systemctl reload nginx

Now, run Certbot to request the SSL certificate:

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

If successful, Certbot will save the certificate files in /etc/letsencrypt/live/example.com/.

Step 6: Configure Nginx for HTTPS

Update your Nginx configuration to enable SSL and redirect HTTP traffic to HTTPS:

server {
    listen 80;
    server_name example.com www.example.com;
    include snippets/acme-challenge.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-params.conf;
    include snippets/acme-challenge.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-params.conf;
    include snippets/acme-challenge.conf;

    # Additional website configuration (root, index, etc.)
}

Reload Nginx again to activate the SSL configuration:

sudo systemctl reload nginx

Step 7: Automate Certificate Renewal

Let's Encrypt certificates are valid for 90 days. It is essential to automate the renewal process. You can create a cron job that runs twice a day to check for expiring certificates and renew them if they are within 30 days of expiration.

Edit the crontab:

sudo crontab -e

Add the following line to the file:

0 */12 * * * root /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

To verify the renewal process works, perform a dry run:

sudo certbot renew --dry-run

If no errors appear, the automated renewal system is correctly configured.

Tags: CentOS 7 nginx Certbot Let's Encrypt SSL/TLS

Posted on Mon, 22 Jun 2026 16:23:32 +0000 by pixelsoul