How to Properly Enable HTTPS on Apache with Let’s Encrypt on Ubuntu 16.04/17.10

This tutorial is going to show you how to properly enable HTTPS on Apache with Let’s Encrypt on Ubuntu 16.04/17.10. Google Chrome and Firefox have already begun marking non-encrypted web pages with password input box as being insecure. Eventually all HTTP web pages will be marked as insecure. HTTPS will become default for any website. It’s also a requirement if you want to utilize the new HTTP/2 protocol to speed up your website.

As you may probably know, Let’s Encrypt is a free, automated, and open certificate authority. The official documentation describes simple steps you can follow to enable HTTPS with Let’s Encrypt, but there’s more to it than that. If you follow the official doc, you get an A on SSL Labs test. If you follow my steps, you will get an A+. If you’ve already deployed a Let’s Encrypt certificate before, you can still follow this tutorial to renew and replace your existing certificate.

Before I show you the steps to enable HTTPS with Let’s Encrypt, I want to first talk about CAA record, security headers and OCSP stapling. These things are what can help you get A+. I will also show you how to deal with CloudFlare CDN service at the end of this tutorial.

Creating CAA Record for Your Domain Name

Certificate Authority Authorization (CAA) is a DNS resource record that specifies which certificate authorities (CAs) are allowed to issue certificate for a particular domain name. Starting September 2017, All CAs are mandated to check CAA records before issuing certificate for a particular domain name. If no CAA record is found for a domain name, then any CAs can issue certificate for that domain name. If a CA is not listed in your CAA record, then that CA cannot issue certificate for your domain name.

To create a CAA record which allows Let’s Encrypt to issue certificate for your domain name, add the following entry in your DNS server or DNS manager.

example.com. IN CAA 0 issue "letsencrypt.org"

You can also use iodef to make CA report malicious certificate issue request to your email address.

example.com. IN CAA 0 iodef "mailto:your-email-address"

The format of the above records is for zone files. Below are a few tips for you.

You can use the following dig command to check your CAA record.

dig example.com CAA

Note that web browsers will not check CAA records.

Security Headers

Security headers are as important as HTTPS, but only a small percentage of HTTPS-enabled sites pay attention to those headers. While a complete discussion about security headers is beyond the scope of this tutorial, I want to talk about the upgrade-insecure-requests and HSTS headers because you can easily enable them with Let’s Encrypt to increase your site’s security.

Upgrade Insecure Requests

There are times when a site has enabled HTTPS, but some CSS, images or JavaScripts are still served over HTTP. In this case, the green padlock at the beginning of browser address bar will disappear. In Google Chrome, it’s replaced by an info icon; In Firefox, it’s replaced by a gray padlock with a yellow triangle. You will want to show a green padlock to site visitors as much as possible and the easy way to fix this problem is to enable upgrade-insecure-requests header, which will force the web browser to use https:// for every http:// resource.

To enable this header, simply add --uir flag when issuing certbot command. Note that this header works on resources hosted on your own domain and resources on third-party domains that support HTTPS. If your web page includes resources on third-party servers that aren’t available over HTTPS, then those resources will be blocked by web browsers, but using this header ensures that your web pages always get a green padlock.

HSTS (HTTP Strict Transport Security)

The HSTS header tells web browsers that all communication should be done via HTTPS. It defends against SSL Striping, which is an attack to downgrade from HTTPS to HTTP. To enable this header, simply add --hsts flag when issuing certbot command.

OCSP Stapling

When a web browser connects to a HTTPS website, it sends an OCSP (Online Certificate Status Protocol) request to the certificate authority (CA) in order to query the revocation status of the website’s SSL certificate. This can delay page loading by 1-3 seconds, according to Firefox telemetry data. To improve performance, website owner can enable OCSP stapling, in which case the web server itself fetches OCSP response signed by CA at regular interval and sends it to web browser, thus eliminating the need for web browser to contact OCSP server.

To enable OCSP stapling, simply add --staple-ocsp flag when issuing certbot command.

OCSP Must Staple

If a hacker make a fake, duplicate website, turn off OCSP staple and also block the web browser’s access to OCSP server, then the web browser will assume it’s OK and proceed to the malicious website. To solve this problem, you can enable OCSP must staple on your website, which tells web browsers that OCSP staple response must be presented by your website during HTTPS connection. So when web browsers connect to a fake website that doesn’t have OCSP staple, it will stop the connection.

To enable OCSP must staple, add --must-staple flag when issuing certbot command.

Installing Let’s Encrypt Client on Ubuntu 16.04/17.10

Now it’s time to get your hands dirty. Starting Ubuntu 16.04, Let’s Encrypt client is included in Ubuntu repository, so you can easily install it on Ubuntu 16.04 with the following command. python-letsencrypt-apache is the Apache plugin.

sudo apt update

sudo apt install letsencrypt python-letsencrypt-apache

On Ubuntu 17.10, the package is called certbot, so you need to run

sudo apt update

sudo apt install certbot python-certbot-apache

There’s also an official PPA. So if you want to install the latest version, use the PPA by running the following commands. software-properties-common is required if you want to install packages from PPA. It’s often missing on a default Ubuntu server Install.

sudo apt update

sudo apt install software-properties-common

sudo add-apt-repository ppa:certbot/certbot

sudo apt update

sudo apt install certbot python-certbot-apache

To check version number, run

certbot --version

Sample output:

certbot 0.19.0

Using Apache Plugin to Enable HTTPS

If your website doesn’t use CDN service, then it’s recommended to use the Apache plugin to enable HTTPS on Apache web server, as it can automatically obtain SSL/TLS certificate and configure it for you. Run the following command on your Ubuntu server.

sudo certbot --apache --agree-tos --redirect --uir --hsts --staple-ocsp --must-staple -d www.example.com,example.com --email your-email-address

Explanation:

  • –apache: Use the Apache authenticator and installer
  • –agree-tos: Agree to Let’s Encrypt terms of service
  • –redirect: Automatically redirect all HTTP traffic to HTTPS
  • –uir: Add the “Content-Security-Policy: upgrade-insecure-requests” header to every HTTP response.
  • –hsts: Add the Strict-Transport-Security header to every HTTP response.
  • –staple-ocsp: Enables OCSP Stapling.
  • –must-staple: Adds the OCSP Must Staple extension to the certificate.
  • -d flag is followed by a list of domain names, separated by comma. You can add up to 100 domain names.
  • –email: Email used for registration and recovery contact.

You will be asked if you want to receive emails from EFF(Electronic Frontier Foundation). After choosing Y or N, your SSL certificate will be automatically obtained and configured for you, which is indicated by the message below.

ubuntu letsencrypt apache2

Now if you visit your website, you can see that HTTP is automatically redirected to HTTPS connection. Please note that certbot client creates /etc/apache2/sites-enabled/example.com-le-ssl.conf SSL virtual host when configuring SSL for your website.

Testing Your SSL Certificate

Go to ssllabs.com to test your SSL certificate and configuration. As I’ve promised, you get A+. You can also check if your domain name has enable CAA record, whether your server has enabled HSTS, OCSP stapling and OCSP must staple.

ubuntu 16.04 certbot apache

Redirecting WWW to Non-WWW (Or Vice-Versa)

We have already enabled redirecting HTTP to HTTPS, what’s left to do is redirect www to non-www, or vice versa. If you are using WordPress, then it’s very easy. Simply go to WordPress Dashboard > Settings > General and set your preferred version (www or non-www) in WordPress Address and Site Address.

letsencrypt apache redirect

If you go that route, you will end up with what’s known as double 301 redirect. First, Apache server redirect HTTP to HTTPS, then WordPress redirects to www or non-www domain.

Some may argue that you can lose SEO link juice when doing double 301 redirect. If you are worried about that, then you can use the method below to make all domain versions to go directly to the final destination.

Edit your virtual host file. (Not the SSL virtual host)

sudo nano /etc/apache2/sites-enabled/example.com.conf

CertBot client added the following lines to the file to redirect HTTP to HTTPS.

RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com [OR]
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

To redirect to www or non-www domain, you need to change the last line. Replace %{SERVER_NAME} with your preferred domain version like below. (www domain)

RewriteRule ^ https://www.example.com%{REQUEST_URI} [END,NE,R=permanent]

If you prefer non-www domain, change it to the following.

RewriteRule ^ https://example.com%{REQUEST_URI} [END,NE,R=permanent]

Then save and close the file. We will also need to edit the SSL virtual host.

sudo nano /etc/apache2/sites-enabled/example.com-le-ssl.conf

Add the following lines to above the closing </VirtualHost> tag to redirect non-www to www domain.

RewriteEngine on
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://www.example.com%{REQUEST_URI} [END,NE,R=permanent]

If you want to redirect www to non-www domain, add the following lines instead.

RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com
RewriteRule ^ https://example.com%{REQUEST_URI} [END,NE,R=permanent]

Save and close the file. Reload Apache service for the changes to take effect.

sudo systemctl reload apache2

To be more clear, below is a screenshot of my Apache virtual host file and SSL virtual host file for redirecting non-www to www domain.

certbot apache virtual host

Apache Virtual Host File

letsencrypt apache virtual host

Apache SSL Virtual Host File

If you are using WordPress, make sure you set your preferred domain version in WoredPress Address and Site Address before editing Apache virtual host files. If WordPress settings contradicts with Apache configuration, your site will be in a redirect loop.

Certificate Auto Renewal

To automatically renew Let’s Encrypt certificate, simply edit root user’s crontab file.

sudo crontab -e

Then add the following line at the bottom.

@ certbot renew --quiet && systemctl reload apache2

--quiet flag will suppress normal messages. If you want to receive error messages, then add the following line at the beginning of crontab file.

MAILTO=your-email-address

Reloading Apache is needed for it for present the new certificate to clients.

CloudFlare CDN

The first thing you need to know is that if you want to install Let’s Encrypt certificate on your server and at the same time use CloudFlare’s CDN service, then you will need to enable CloudFlare’s Universal SSL on your site, which means connections between site visitors and CloudFlare edge server are encrypted using CloudFlare Universal SSL certificate and communications between your origin server and CloudFlare edge server are encrypted using Let’s Encrypt issued certificate.

If you install Let’s Encrypt certificate on your origin server, redirect HTTP to HTTPS and turn off CloudFlare Universal SSL, the web browsers will complain that your website is in a infinite redirect loop because CloudFlare redirect HTTPS to HTTP.

The second thing you need to know is that if you want to enable CAA record while using CloudFlare Universal SSL, then you also need to create the following CAA record.

example.com. IN CAA 0 issue "comodoca.com"

example.com. IN CAA 0 issue "digicert.com"

example.com. IN CAA 0 issue "globalsign.com

Follow this post to add CAA record for CloudFlare Universal SSL certificate.

So how do you go about installing Let’s Encrypt certificate with CloudFlare? Well, there are two scenarios.

  1. You’ve already installed Let’s Encrypt certificate using the above steps, now you want to enable CloudFlare CDN service.
  2. Your website is using CloudFlare CDN service, now you want to install Let’s Encrypt certificate on your origin server.

The First Scenario

If you are in the first scenario, then you can go ahead and enable CloudFlare CDN service and also enable CloudFlare Universal SSL in CloudFlare Dashboard by going to Crypto > SSL and choosing Full (Strict). Your site will be working fine without a problem.

The Second Scenario

The Certbot Apache plugin uses Apache as both the authenticator and installer. The Apache authenticator uses the tls-sni-01 challenge to prove domain control. That means Certbot needs to set up a temporary TLS server listening on port 443. It won’t work if your site is behind a CDN like CloudFlare as Let’s Encrypt authenticate server can’t see your origin IP, thus can’t reach the temporary TLS server on your origin server.

If you use CloudFlare CDN and now you want to install Let’s Encrypt on your origin server, then you will need to use the webroot authenticator to prove domain control and use Apache installer to automatically configure SSL/TLS. Specify authenticator with --authenticator flag and the installer with --installer flag like below. /var/www/html/ is the path to web root. Change it accordingly.

sudo certbot --authenticator webroot --installer apache -w /var/www/html/ --agree-tos --redirect --uir --hsts --staple-ocsp --must-staple -d www.example.com,example.com --email your-email-address

After the certificate is obtained and installed on your server, remember to enable CloudFlare Universal SSL.

I hope this tutorial helped you enable HTTPS on Apache virtual host with Let’s Encrypt on Ubuntu 16.04/17.10. As always, if you found this post useful, then subscribe to our free newsletter. In the next tutorial, we will see how to enable HTTP/2 protocol with Apache to speed up website.

Rate this tutorial
[Total: 3 Average: 5]