Secure Apache with Let's Encrypt on CentOS 7

Updated on

5 min read

How to use Let's Encrypt with Apache on CentOS 7

Let’s Encrypt is a free, automated, and open certificate authority developed by the Internet Security Research Group (ISRG). Certificates issued by Let’s Encrypt are valid for 90 days from the issue date and are trusted by all major browsers today.

In this tutorial, we’ll cover the steps necessary to install a free Let’s Encrypt SSL certificate on a CentOS 7 server running Apache as a web server. We’ll use the certbot utility to obtain and renew Let’s Encrypt certificates.

Prerequisites

Ensure that you have met the following prerequisites before continuing with this tutorial:

Install the following packages which are required for an SSL encrypted web server:

yum install mod_ssl openssl

Install Certbot

Certbot is a tool that simplifies the process for obtaining SSL certificates from Let’s Encrypt and auto-enabling HTTPS on your server.

The certbot package is aveiable for installation from EPEL. If the EPEL repository is not installed on your system, you can install it using the following command:

sudo yum install epel-release

Once the EPEL repository is enabled, install the certbot package by typing:

sudo yum install certbot

Generate Strong Dh (Diffie-Hellman) Group

Diffie–Hellman key exchange (DH) is a method of securely exchanging cryptographic keys over an unsecured communication channel. Generate a new set of 2048 bit DH parameters to strengthen the security:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
You can change the size up to 4096 bits, but in that case, the generation may take more than 30 minutes depending on the system entropy.

Obtaining a Let’s Encrypt SSL certificate

To obtain an SSL certificate for our domain, we’re going to use the Webroot plugin that works by creating a temporary file for validating the requested domain in the ${webroot-path}/.well-known/acme-challenge directory. The Let’s Encrypt server makes HTTP requests to the temporary file to validate that the requested domain resolves to the server where certbot runs.

To make it more simple we’re going to map all HTTP requests for .well-known/acme-challenge to a single directory, /var/lib/letsencrypt.

Run the following commands to create the directory and make it writable for the Apache server:

sudo mkdir -p /var/lib/letsencrypt/.well-knownsudo chgrp apache /var/lib/letsencryptsudo chmod g+s /var/lib/letsencrypt

To avoid duplicating code create the following two configurations snippets:

/etc/httpd/conf.d/letsencrypt.conf
Alias /.well-known/acme-challenge/ "/var/lib/letsencrypt/.well-known/acme-challenge/"
<Directory "/var/lib/letsencrypt/">
    AllowOverride None
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    Require method GET POST OPTIONS
</Directory>
/etc/httpd/conf.d/ssl-params.conf
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options SAMEORIGIN
Header always set X-Content-Type-Options nosniff
# Requires Apache >= 2.4
SSLCompression off
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Requires Apache >= 2.4.11
SSLSessionTickets Off

The snippet above includes the recommend chippers, enables OCSP Stapling, HTTP Strict Transport Security (HSTS) and enforces few security‑focused HTTP headers.

Reload the Apache configuration for changes to take effect:

sudo systemctl reload httpd

Now, we can run Certbot tool with the webroot plugin and obtain the SSL certificate files by typing:

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

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

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2018-12-07. 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:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

CentOS 7 ships with Apache version 2.4.6, which does not include the SSLOpenSSLConfCmd directive. This directive is only available on Apache 2.4.8 later, and it is used for configuration of OpenSSL parameters such as Diffie–Hellman key exchange (DH).

We will have to create a new combined file using the Let’s Encrypt SSL certificate and the generated DH file. To do this, type:

cat /etc/letsencrypt/live/example.com/cert.pem /etc/ssl/certs/dhparam.pem >/etc/letsencrypt/live/example.com/cert.dh.pem

Now that everything is set up, edit your domain virtual host configuration as follows:

/etc/httpd/conf.d/example.com.conf
<VirtualHost *:80>
  ServerName example.com
  ServerAlias www.example.com

  Redirect permanent / https://example.com/
</VirtualHost>

<VirtualHost *:443>
  ServerName example.com
  ServerAlias www.example.com

  <If "%{HTTP_HOST} == 'www.example.com'">
    Redirect permanent / https://example.com/
  </If>

  DocumentRoot /var/www/example.com/public_html
  ErrorLog /var/log/httpd/example.com-error.log
  CustomLog /var/log/httpd/example.com-access.log combined

  SSLEngine On
  SSLCertificateFile /etc/letsencrypt/live/example.com/cert.dh.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
  SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

  # Other Apache Configuration

</VirtualHost>

With the configuration above, we are forcing HTTPS and redirecting from www to non-www version. Fell free to adjusts the configuration according to your needs.

Restart the Apache service for changes to take effect:

sudo systemctl restart httpd

You can now open your website using https:// and you’ll notice a green lock icon.

If you test your domain using the SSL Labs Server Test , you’ll get an A+ grade as shown below:

SSLLABS Test

Auto-renewing Let’s Encrypt SSL certificate

Let’s Encrypt’s certificates are valid for 90 days. To automatically renew the certificates before they expire, we will create a cronjob that will run twice a day and automatically renew any certificate 30 days before its expiration.

Run the crontab command to create a new cronjob which will renew the certificate, create a new combined file including the DH key and restart apache :

sudo crontab -e
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 httpd"

Save and close the file.

To test the renewal process, you can use the certbot command followed by the --dry-run switch:

sudo certbot renew --dry-run

If there are no errors, it means that the renewal process was successful.

Conclusion

In this tutorial, you used the Let’s Encrypt client certbot to download SSL certificates for your domain. You have also created Apache snippets to avoid duplicating code and configured Apache to use the certificates. At the end of the tutorial, you have set up a cronjob for automatic certificate renewal.

If you want to learn more about how to use Certbot, their documentation is a good starting point.

If you have any questions or feedback, feel free to leave a comment.

This post is a part of the Install LAMP Stack on CentOS 7 series.
Other posts in this series: