Updated on 9.5.2024

How to install Let’s Encrypt on Nginx

Improving your website security through encryption, even on the most basic servers, can increase your visitors’ trust in your site and your ability to run it. Setting up encryption on your web host has generally been complicated and expensive, which often deters administrators whose web applications might not depend on user input. Let’s Encrypt aims to change this by making implementing encryption on any website easier. They are an open and free project that allows obtaining and installing certificates through simple, automated commands.

Let's Encrypt Project Logo

Let’s Encrypt is a new Certificate Authority capable of issuing certificates cross-signed by IdentTrust, which allows their end certificates to be accepted by all major browsers.  This guide outlines the steps for installing their Certbot client and how to use it to manage certificates on your CentOS 7 server running nginx.

Installing Let’s Encrypt client

Let’s Encrypt greatly simplifies server management by automating the obtaining of certificates and configuring web services to use them. The client is fully featured and extensible for the Let’s Encrypt Certificate Authority or any other CA that supports the ACME protocol.

On CentOS, the client is available in the Extra Packages for Enterprise Linux (EPEL) which you will need first to install and update.

sudo yum install epel-release
sudo yum update

You will also need to have nginx installed and running. Of course, if you are adding certificates onto a previously configured web host, this will already be installed.

sudo yum install nginx
sudo systemctl start nginx

Then, install the certbot client using the following command.

sudo yum install certbot python2-certbot-nginx

Once installed, you can use the next command to see test the client is working correctly.

certbot --help

Given that the help command works, the client is good to go. Next, follow the instructions below to check that your firewall is configured correctly.

Allow HTTP/S at firewall

CentOS 7 has enabled relatively strict firewall rules by default that do not allow HTTP or HTTPS connections to the host. The Let’s Encrypt client requires access to authenticate the domain name and will fail with the default rules.

If you install the certificates on a previously configured web host, the required rules are probably already set. Confirm the firewall rules with the—- list-services command, and then proceed to the next section to obtain the certificates.

Enable connections for HTTP and HTTPS services using the following command.

sudo firewall-cmd --permanent --add-service=http --add-service=https

Then, reload the firewall rules to apply the changes.

sudo firewall-cmd --reload

You can check that the rules were added successfully with the command below.

sudo firewall-cmd --list-services
dhcpv6-client http ssh https

You should see at least the four services enabled, as shown above. With the firewall configured, you can continue obtaining and installing certificates.

Obtaining a certificate

Let’s Encrypt validates the domain installed on, similarly to a traditional CA process, by identifying the server administrator via a public key. The client generates a new key pair when interacting with the Let’s Encrypt servers for the first time and then aims to prove to the CA that the host has control over a particular domain in at least one of the two following ways:

  • Provisioning a DNS record under the domain in question
  • Provisioning an HTTP resource under a well-known URI on the domain

On top of one of the two challenges, the client also must sign a nonce with its private key to prove it controls that key pair.

To help the Let’s Encrypt client accomplish these tasks, it supports several plugins that can be used to obtain and install certificates. Let’s Encrypt supports automated installation on nginx, the certificates can be easily obtained using the --nginx plugin together with other commands.

The --nginx plugin automates obtaining certificates from the CA when using Nginx web server software. To use this plugin on the command line, use the example below. Replace the example domain in red with your own.

sudo certbot --nginx -d example.upcloud.com

The command starts an interactive configuration script that asks a couple of questions to help with managing certificates.

  1. You must enter a contact email on the first installation on any specific host.
  2. Then go through the Let’s Encrypt Terms of Service and select Agree if you accept the terms and wish to use the service.
  3. Choose whether you wish to share your email address with the Electronic Frontier Foundation (EFF) for updates on their work.
  4. Lastly, enable redirection to HTTPS to secure your domain fully.

If the client successfully obtained a certificate, the client output includes a confirmation and certificate expiration date.

If you are having problems with the client, make sure you are trying to register a domain or subdomain that currently resolves to your server. Also, check that you have the administrative privileges to run the commands and that your domain is pointing to the correct IP address.

Renewing a certificate

At the end of the certificate-obtaining script, the output shows the certificate’s expiration date, which is usually three months from the day it was issued. Renewing a certificate is just as easy as obtaining one.

The client will only renew certificates close to their expiry date, but you can test that the renewal works using the --dry-run parameter to simulate the process.

sudo certbot renew --dry-run

To renew certificates, simply leave out the simulation parameter.

sudo certbot renew

Once the renewal is complete, reload your web service using the following command to update the configuration to include the new certificates.

sudo nginx -s reload

Your certificate is now again valid for another 3 months.

Considering the duration of the certificates, you might wish to automate the renewal with a short script like the example below and make it executable.

sudo vi /etc/cron.daily/letsencrypt-renew
#!/bin/sh
if certbot renew > /var/log/letsencrypt/renew.log 2>&1 ; then
   nginx -s reload
fi
exit
sudo chmod +x /etc/cron.daily/letsencrypt-renew

The example script runs the renewal while directing the output to a log file and then reloads nginx if the process was successful in completing the renewal.

You can then automate the script using Crontab. Open the root user crontab for edit with the command underneath.

sudo crontab -e

Include a line like the example below in the crontab file, then save and exit.

01 02,14 * * * /etc/cron.daily/letsencrypt-renew

Let’s Encrypt recommends setting the automated renewal script to run twice a day at a random minute within the hour. The above example runs at 02:01 and 14:01, but you can select any time slot you wish.

Revoking a certificate

If you wish to remove a certificate from your server, it can be revoked using the client’s subcommand. The command below can be used to revoke a particular certificate. Replace the domain_name with the domain which certificate you wish to revoke.

sudo certbot revoke --cert-path /etc/letsencrypt/live/domain_name/cert.pem

The process does not confirm upon completion, but if you perform it again, you will get a message that the certificate has already been revoked.

Enhancing security

Once the certificate and chain are saved on the server, you can check the Nginx configuration to tune the HTTPS connection further using the new certificates.

Only use secure protocols

As technologies develop, old versions are disused, and the same applies to security protocols. The old insecure SSLv2 and SSLv3 should be disabled and never used on modern web servers. This is due to the inherent insecurities in these protocols, which is why they have been replaced by the TLS protocols. The example below enables the two most secure TLS versions, 1.1 and 1.2.

ssl_protocols TLSv1.1 TLSv1.2;

Note that TLS v1.0 is already a legacy protocol and should be avoided. However, older web browsers might still need to be allowed to work. Enable it only if necessary.

Enable HTTP Strict Transport Security (HSTS)

Strict Transport Security safeguards TLS by not allowing insecure communication with the websites that use it. It was designed to ensure security even in the case of configuration problems and implementation errors. HSTS automatically converts all plaintext links to a secure version. It also disables click-through certificate warnings, which indicate an active MITM attack, and prevents users from circumventing the warning.

Enable HSTS by using the option shown below.

add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";

Enhance cypher suites

The cypher suites enable security between your web server and visitor clients by defining how secure communication occurs. The example configuration below is designed for RSA and ECDSA keys and is a great starting point for improved security.

ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256;

By using SSL protocols of SSLv3 or newer, the client tells the web server which cypher suites it supports, and the server chooses one option from that list. The important part of this functionality is that the cyphers on the server are listed in the preferred order from the strongest to the weakest, and the cypher order is honoured. This feature can be enforced by adding the following line in your configuration file.

ssl_prefer_server_ciphers on;

Diffie-Hellman Ephemeral algorithm

The Diffie-Hellman algorithm is a way of generating a shared secret between two parties in such a way that the secret cannot be seen by observing the communication. It is a useful technique to create an encryption key between a server and a client, that then uses the shared key to encrypt their traffic. Ephemeral Diffie-Hellman (DHE) differs from static Diffie-Hellman in that it generates a temporary key for every connection and never uses the same key twice. This enables forward secrecy, which means that even if the server’s long-term private key gets leaked, previous communication will remain secure.

Generate a strong DHE parameter using the command below.

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

The process takes but a moment with a 2048-bit key length. You can also use a 4096-bit length for higher security, but generating a longer parameter will be considerably slower.

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

Afterwards, the output can be used in the Nginx configuration using the above example.

Redirect unencrypted connections

Optionally, you can redirect your HTTP connections to encrypted HTTPS. By creating the HTTP server segment, as shown in the example below, you can tell your web server to listen for regular HTTP traffic and upgrade these connections to secure ones. Again, replace the domain_name with your web server’s domain. The rest of that segment can remain as is.

server {
   listen 80;
   server_name domain_name;
   return 301 https://$server_name$request_uri;
}

This will redirect all connections to the encryption-enabled https:// part of your site, even with links pointing to the http://domain_name address.

Adding it all to the configuration

With CentOS or other Red Hat variants, Certbot saves the Nginx configuration file to /etc/letsencrypt/options-ssl-nginx.conf, but editing it directly will prevent Certbot from updating the file later. Instead, create a new configuration file with the command below.

sudo vi /etc/nginx/conf.d/domain_name.conf

This example configuration sets up a single site listening for HTTPS connections with the added security features explained above. In the example underneath, replace domain_name with your own domain.

# HTTPS server
server {
   listen 443 ssl;
   server_name domain_name;
   ssl_certificate /etc/letsencrypt/live/domain_name/fullchain.pem;
   ssl_certificate_key /etc/letsencrypt/live/domain_name/privkey.pem;
   ssl_session_cache shared:SSL:10m;
   ssl_session_timeout 5m;
   ssl_protocols TLSv1.1 TLSv1.2;
   ssl_prefer_server_ciphers on;
   ssl_dhparam /etc/ssl/certs/dhparam.pem;
   ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256;
   add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
   location / {
      root /usr/share/nginx/html;
      index index.html index.htm;
   }
}

# HTTP redirect
server {
   listen 80;
   server_name domain_name;
   return 301 https://$server_name$request_uri;
}

Then, save the file and exit the editor.

To have the changes take effect, you will need to restart nginx.

sudo systemctl restart nginx

Now open your domain in a web browser using https://domain_name. When it loads, you will know the installation is working properly.

You can evaluate server encryption performance with Qualys SSL Labs test site. Enter your domain name into the text field and click the Submit button. The test will take a moment, but when completed, it provides useful information on different areas of your server encryption security and an overall rating.

Qualys SSL Labs nginx test

Let’s Encrypt is still in development and might include certain rate limits for issuing certificates to protect the service against accidental and intentional abuse. You can check further details in the Let’s Encrypt documentation.

Other plugins

In most cases, simply installing and renewing your certificates as instructed above is enough, but the Let’s Encrypt client also supports some additional plugins for managing your certificates. For example, if you do not have a web service configured yet while obtaining a new certificate, you can use the—-standalone plugin with the certonly subcommand.

This guide focuses on installing the certificate on Nginx using the—- nginx plugin, though Let’s Encrypt works just as well with other web server software. It also has built-in support for issuing and installing certificates automatically for servers running Apache. Check out our guide for how to install Let’s Encrypt on Apache2 to learn more. You can also learn about other supported options in the documentation for Let’s Encrypt.

Janne Ruostemaa

Editor-in-Chief

  1. https://letsencrypt.org/docs/faq/

    Letsencrypt recommend automatically renewing your certificates every 60 days. (not twice every day)

  2. Janne Ruostemaa

    Hi Jen, thanks for the comment. You are right in that the certificate should be renewed every 60 days. However, the approach of having the renew attempted every day is a feature of the Certbot client. The renew command only attempts to complete the process once the certificate is going to expire in 30 days or less. Since the client only attempts to renew certificates that are near expiry it can be run as frequently as you want – since it will usually take no action. You can read more about automating renewal at Certbot documentation https://certbot.eff.org/docs/using.html#renewal

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top