Securing NGINX with SSL using Let’s Encrypt on CentOS 7.x

In April 2016, Let’s Encrypt was launched and gave everyone access to free SSL certificate. There is no reason not to secure your site with HTTPS. In this tutorial, we will be showing you how to secure NGINX hosted sites on CentOS 7.x with Let’s Encrypt.

Before You Get Started

In this tutorial we assumed you have your domain name pointed to a public IP address and has the domain properly resolved to that particular IP address. Secondly, You have EPEL repo enabled and NGINX installed.

Install Certbot

We will start by installing Certbot – a Let’s Encrypt client to assist with automation and renewals of the SSL certificate that were issued by Let’s Encrypt.

sudo yum install certbot

Preparing Webroot folder and NGINX Configs

Let’s Encrypt requires HTTP request validation before it can issue a certificate when using Webroot plugin to generate the SSL – hence why we are going to start by creating the webroot folder.

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

Next, we are going to create an NGINX configuration file to include the webroot path we had created above into NGINX server block – Feel free to use your favorite text editor – in this case we are using nano.

sudo mkdir /etc/nginx/letsencrypt/
sudo nano -w /etc/nginx/letsencrypt/webroot.conf
/etc/nginx/letsencrypt/webroot.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/www/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}
sudo nano -w /etc/nginx/letsencrypt/ssl.conf
/etc/nginx/letsencrypt/ssl.conf
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";

The next step is to add these “include config” into our site’s NGINX configuration under server block. For this example, we will be using the domain name “domain.com”.

/etc/nginx/conf.d/domain.com.conf
server {
  listen 80;
  server_name domain.com www.domain.com;
  include letsencrypt/webroot.conf;
}

We will restart NGINX for the changes to take effect.

sudo systemctl restart nginx

Obtaining and Installing the SSL certificate

With the webroot and http request validation ready, you can now request the certificate from Let’s Encrypt with certbot. 

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

Once the certificate is issued, you will be able to find both certificate and chain file in /etc/letsencrypt/live/domain.com/ folder – you will see four files; cert.pem, chain.pem, fullchain.pem and privkey.pem

Next, we will install the certificate by adding it to our NGINX server block configuration – we will also force non-https URI to https during this process and force www to non www (For ex. www.domain.com will redirect to domain.com)

/etc/nginx/conf.d/domain.com.conf
server {
    listen 80;
    server_name domain.com www.domain.com;
    include letsencrypt/webroot.conf;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name domain.com;

    ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
    include letsencrypt/ssl.conf;
    include letsencrypt/webroot.conf;
}

server {
    listen 443 ssl;
    server_name www.domain.com;

    ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
    include letsencrypt/ssl.conf;
    include letsencrypt/webroot.conf;
 
    #redirect www.domain.com to domain.com
    return 301 https://domain.com$request_uri;
}

Finally, the last step is to restart NGINX

sudo systemctl restart nginx

Automating SSL Renewal

Let’s Encrypt certificate expires every 90 days; yes it is shorter than most commercial SSL certificates – however, you can automate the renewal with certbot. To do so, we will utilize cron to run renewal process.

sudo crontab -e

Add this line to your crontab

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

You can also simulate a renewal test by running this command

/usr/bin/certbot renew --dry-run

Final Take

Moving your sites to HTTPS is a step in helping making the web a better and safer place – the open source community is making it easier by providing various tools to get us there. 

If you need more help on using Certbot, please refer to the documentation provided by the project. Feel free to leave comment or suggestions below. We will update this tutorial as thing changes.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.