How to Secure Nginx with Let’s Encrypt and Certbot on RHEL 7
Let’s Encrypt is a free, automated, and open Certificate Authority (CA) that provides SSL/TLS certificates to enable HTTPS on your web server. Certbot is the official client tool for obtaining and renewing Let’s Encrypt certificates. On RHEL 7, Certbot is available through the EPEL repository as the python-certbot-nginx package. When used with the --nginx plugin, Certbot can automatically obtain a certificate and modify your existing Nginx server block configuration to enable HTTPS, handling much of the complexity for you. This tutorial covers installing Certbot, obtaining a certificate for your domain, understanding the automatic configuration changes Certbot makes, setting up automatic renewal, and testing your SSL configuration.
Prerequisites
- Nginx installed and running on RHEL 7 with a server block configured for your domain
- A registered domain name with a DNS A record pointing to your server’s public IP address
- Ports 80 and 443 open in
firewalld - Root or
sudoaccess - The EPEL repository enabled
Let’s Encrypt validates domain ownership by making an HTTP request to your server on port 80. Ensure port 80 is reachable from the internet before proceeding. The certificate will be issued for a real, publicly resolvable domain — you cannot obtain a certificate for localhost or a private IP address.
Step 1: Enable the EPEL Repository
If you have not already enabled EPEL, install the release package first:
sudo yum install epel-release -y
If epel-release is not available from your configured repositories, install it directly from the Fedora project:
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
Verify EPEL is enabled:
yum repolist | grep epel
Step 2: Install Certbot and the Nginx Plugin
Install the Certbot package along with the Nginx plugin from EPEL:
sudo yum install certbot python-certbot-nginx -y
Verify the installation:
certbot --version
Expected output (version numbers may vary):
certbot 1.11.0
The python-certbot-nginx plugin allows Certbot to read your existing Nginx configuration, obtain the certificate, and automatically update the server block files to serve HTTPS — all in a single command.
Step 3: Verify Your Nginx Server Block Configuration
Before running Certbot, ensure your Nginx server block has the correct server_name directive pointing to your domain. Certbot uses this to determine which domain to request a certificate for. Open your virtual host configuration file:
sudo cat /etc/nginx/conf.d/example.com.conf
Confirm it contains a server_name matching your domain:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Test the Nginx configuration to ensure it is valid before proceeding:
sudo nginx -t
Step 4: Open Port 443 in the Firewall
If you have not already done so, allow HTTPS traffic through firewalld:
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --reload
Verify both HTTP and HTTPS are permitted:
sudo firewall-cmd --zone=public --list-services
Step 5: Obtain a Certificate with Certbot
Run Certbot with the --nginx plugin and specify your domain name with the -d flag. To include both the bare domain and the www. subdomain in the same certificate, list both with -d:
sudo certbot --nginx -d example.com -d www.example.com
Certbot will prompt you for the following:
- Email address — Used for urgent renewal and security notices from Let’s Encrypt.
- Terms of service — You must agree to the Let’s Encrypt Subscriber Agreement.
- Email sharing — Optional, whether to share your address with the Electronic Frontier Foundation.
- HTTP to HTTPS redirect — Certbot asks whether to redirect all HTTP traffic to HTTPS. Choosing option 2 (Redirect) is recommended for production sites.
After successful validation and certificate issuance, Certbot modifies your Nginx configuration file automatically. The certificate files are stored in:
- Certificate:
/etc/letsencrypt/live/example.com/fullchain.pem - Private key:
/etc/letsencrypt/live/example.com/privkey.pem
Step 6: Review the Modified Nginx Configuration
After Certbot runs, review the changes it made to your server block file:
sudo cat /etc/nginx/conf.d/example.com.conf
Certbot will have added or modified the configuration to include something similar to:
server {
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = www.example.com) {
return 301 https://$host$request_uri;
}
if ($host = example.com) {
return 301 https://$host$request_uri;
}
listen 80;
server_name example.com www.example.com;
return 404;
}
The /etc/letsencrypt/options-ssl-nginx.conf file contains strong SSL settings recommended by Certbot, including protocol versions and cipher suites. Do not remove this include.
Step 7: Test the Nginx Configuration and Reload
After Certbot has made its changes, test the configuration one more time:
sudo nginx -t
Then reload Nginx to ensure the latest configuration is active:
sudo systemctl reload nginx
Step 8: Test SSL with curl
Verify that HTTPS is working correctly by requesting the HTTPS URL with curl:
curl -I https://example.com
A successful response will include HTTP/1.1 (or HTTP/2) with a 200 OK status and an SSL connection established without certificate errors. The response headers will include:
HTTP/1.1 200 OK
Server: nginx/1.24.0
Content-Type: text/html
...
Test that the HTTP-to-HTTPS redirect is working:
curl -I http://example.com
You should see a 301 Moved Permanently response with a Location: https://example.com/ header.
To view the full SSL certificate details returned by the server:
curl -v https://example.com 2>&1 | grep -A 10 "SSL connection"
Step 9: Set Up Automatic Certificate Renewal
Let’s Encrypt certificates are valid for 90 days. Certbot includes a built-in renewal mechanism. Test the renewal process without actually renewing:
sudo certbot renew --dry-run
If the dry run completes without errors, automatic renewal is configured correctly. Certbot installs a cron job or systemd timer during installation to handle renewals automatically. Verify the cron job exists:
sudo cat /etc/cron.d/certbot
You should see something like:
0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q
This runs Certbot twice daily at midnight and noon. The random sleep prevents all Certbot clients from hitting Let’s Encrypt servers simultaneously.
If the cron job is not present, create one manually:
sudo crontab -e
Add the following line:
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
The --post-hook option ensures Nginx is reloaded after a successful renewal so the new certificate is loaded into memory. The --quiet flag suppresses output unless there is an error.
Step 10: Verify Renewal Configuration
Certbot stores renewal configuration for each certificate in /etc/letsencrypt/renewal/. Review the renewal configuration for your domain:
sudo cat /etc/letsencrypt/renewal/example.com.conf
This file specifies which authenticator plugin and Nginx configuration path to use during renewal. Certbot reads this file automatically during the renewal process. Do not delete or modify it unless you are intentionally changing the renewal configuration.
List all certificates managed by Certbot and their expiry dates:
sudo certbot certificates
Output example:
Found the following certs:
Certificate Name: example.com
Domains: example.com www.example.com
Expiry Date: 2026-08-15 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
Conclusion
You have successfully secured your Nginx web server on RHEL 7 with a free SSL/TLS certificate from Let’s Encrypt using Certbot. Your site now serves content over HTTPS with a valid, browser-trusted certificate, and all HTTP requests are automatically redirected to HTTPS. Certbot has been configured to renew the certificate automatically before it expires, ensuring continuous HTTPS availability without manual intervention. With HTTPS in place, your server encrypts all data in transit between clients and the server, protecting user privacy and improving your search engine ranking. The next step is to review the SSL configuration in /etc/letsencrypt/options-ssl-nginx.conf and consider additional hardening measures such as HSTS (HTTP Strict Transport Security) headers.