Updated: November 2020

Overview

This post is the sixth of a 6-post series with step-by-step procedures that I use to setup a simple WordPress website on AWS. In this post, the steps to upgrade access on this AWS webserver to https (i.e., padlock icon on browser’s address bar) are detailed.

Note: The original version for this series was written in 2016 with EC2 servers running Ubuntu 16.04. This series has been completely updated in late 2020. An example website, Seattle Hobbies, will be used throughout this series. The development of the Seattle Hobbies website assumes a simple low-maintenance website with low visitor count with no auto-scaling or redundancy. As such, implementation and configuration are easy. I will most likely seek the support of web-dev experts if I want to establish a sophisticated website that handles commerce or significant traffic with lots of site visitors.

HTTPS

HTTPS (Hyper Text Transfer Protocol Secure) is an access protocol that allows a web browser to connect securely with a web server. HTTPS is one of the basic mechanisms to secure a web browsing session since communication traffic flow is encrypted. To implement HTTPS on an AWS EC2 Apache web server hosting a WordPress website requires creation of an TSL/SSL certificate to encrypt the traffic between a web server and a web browser.

AWS EC2 Security Group Changes

Since HTTPS internet communications occur on port 443, we need to add this port for the in-bound traffic. If the steps in AWS WordPress 1: Create EC2 Instance were followed, port 443 has been included during creation of the Security Group.

To add port 443, select the ‘Services’ pull-down menu (or click on EC2 if it is visible in ‘Recently visited sites’) and click on EC2. Click on ‘Security Groups’ and select the security group (e.g., ‘example-security-1’) associated with the instance created for this series. Selecting the ‘Inbound’ tab should display a list of listeners as shown below:

Click on ‘Edit’ and add the following two entries for type (‘HTTPS’, which will result in the ‘Custom TCP Rule’ type), port (443) and sources (0.0.0.0/0 and ::/0). For this example series, keeping the SSH port 22 accessible from all internet addresses is tolerable. For a real development or production EC2 instance, the SSH internet address source should be constrained to specific internet addresses associated with admin/developers to improve security.

Install Certbot repository

At this point, we need to fetch and deploy on our web server an authoritative SSL/TLS certificate for encrypted communication. Cerbot is a software client that, in our case, is installed on the EC2 Ubuntu instance. Cerbot fetches and deploys SSL/TLS certificates from Let’s Encrypt for web servers. To add the Cerbot repository to the EC2 instance, log into AWS SSH as user2 (e.g., alternate user from previous post) via a command line interface (e.g., terminal on the Mac or PuTTY on Windows) as described in AWS WordPress 2: Improve Security. The following steps install cerbot, verify installation with a version check, and ensure that cerbot can be executed.

sudo snap install --classic certbot

certbot --version

sudo ln -s /snap/bin/certbot /usr/bin/certbot

Certificate installation

To install a single certificate that is valid for multiple domains or subdomains, the domains are passed as additional parameters to the certbot command. The first domain name in the list should be the base domain (e.g., seattlehobbies.com) used by Let’s Encrypt to create the certificates. For this example, the subdomain www.seattlehobbies.com is included.

sudo certbot --apache -d seattlehobbies.com,www.seattlehobbies.com

Sometimes, the first time executing this command results in challenge errors. If that happens, running the command a second time seems to work cleanly. During execution of this command, there are several notes and a prompt asking about which virtual host should be selected. Select the option that has wordpress-le-ssl.conf. When the certificate installation has completed, the certificate files should be located in this folder ‘/etc/letsencrypt/live’.

To conduct an SSL/TSL server test of the certificate, go to SSL Labs and enter the website address (e.g., https://seattlehobbies.com). Although the goal is to get the successful result shown in the following diagram, I am truly amazed by the amount of information (not reproduced here) produced by SSL Labs during this SSL/TSL server test.

Certificate Renewals

SSL/TLS certificates expire (e.g., after 90 days). To renew the certificate, we can conduct a dry-run of the renewal with cerbot:

sudo certbot renew --dry-run

To automatically renew the Let’s Encrypt certificate, we will edit the root users crontab file:

sudo crontab -e

When the command prompts for selection of a CLI editor to use, select ‘nano’. Then, add the following line to the bottom of the file:

@daily certbot renew --quiet && systemctl reload apache2

Then, press ctrl-x, type y, and return to save.

Configure WordPress to use https

Although the web server is now using the SSL/TLS certificate and accepting https communication, we still need to update the configuration of WordPress to support https access. First we need to update a few files via SSH from either terminal (Mac OS) or PuTTY (Windows) using ‘nano’ as the CLI editor.

The first file to update is the ‘wp-config.php’ file located in ‘/var/www/wordpress’. Navigate to this folder and edit this file:

cd /var/www/wordpress
sudo nano wp-config.php

Add the following two lines just above the /* That’s all, stop editing! Happy blogging. */ line:

define('WP_HOME','https://seattlehobbies.com');
define('WP_SITEURL','https://seattlehobbies.com');

Enter ctrl-x, type y, and return to save.

The second file to update is the ‘wordpress.conf’ file located in ‘/etc/apache2/sites-available’). Navigate to this folder and edit this file:

cd /etc/apache2/sites-available
sudo nano wordpress.conf

Update the contents to match the following:

<VirtualHost *:80>
  ServerName seattlehobbies.com
  DocumentRoot /var/www/wordpress
  DirectoryIndex index.php
  <Directory /var/www/wordpress/>
    AllowOverride All
    Order Deny,Allow
    Allow from all
  </Directory>
  RewriteEngine on
  RewriteCond %{SERVER_NAME} =www.seattlehobbies.com [OR]
  RewriteCond %{SERVER_NAME} =seattlehobbies.com
  RewriteRule ^ https://seattlehobbies.com%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Then, press ctrl-x, type y, and return to save.

The third file to update is the ‘wordpress-le-ssl.conf’ file located in ‘/etc/apache2/sites-available’). Navigate to this folder and edit this file:

cd /etc/apache2/sites-available
sudo nano wordpress-le-ssl.conf

Update the contents to match the following:

<IfModule mod_ssl.c>
  <VirtualHost *:443>
          ServerAdmin admin@seattlehobbies.com
          ServerName seattlehobbies.com
          ServerAlias www.seattlehobbies.com
          DocumentRoot /var/www/wordpress
    DirectoryIndex index.php
    <Directory /var/www/wordpress/>
      AllowOverride All
      Order Deny,Allow
      Allow from all
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/seattlehobbies.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/seattlehobbies.com/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
  </VirtualHost>
</IfModule>

<IfModule mod_ssl.c>
  <VirtualHost *:80>
    ServerName seattlehobbies.com
    DocumentRoot /var/www/wordpress
    DirectoryIndex index.php
    <Directory /var/www/wordpress/>
      AllowOverride All
      Order Deny,Allow
      Allow from all
    </Directory>
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =www.seattlehobbies.com [or]
    RewriteCond %{SERVER_NAME} =seattlehobbies.com
    RewriteRule ^ https://seattlehobbies.com%{REQUEST_URI} [END,NE,R=permanent]
  </VirtualHost>
</IfModule>

Then, press ctrl-x, type y, and return to save.

The fourth file to update is the ‘.htaccess’ file located in ‘/var/www/wordpress/’) Navigate to this folder and edit this file:

cd /var/www/wordpress
sudo nano .htaccess

Update the contents to match the following:

## EXPIRES CACHING ##
<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpg "access plus 1 year"
  ExpiresByType image/jpeg "access plus 1 year"
  ExpiresByType image/gif "access plus 1 year"
  ExpiresByType image/png "access plus 1 year"
  ExpiresByType text/css "access plus 1 month"
  ExpiresByType application/pdf "access plus 1 month"
  ExpiresByType text/x-javascript "access plus 1 month"
  ExpiresByType application/x-shockwave-flash "access plus 1 month"
  ExpiresByType image/x-icon "access plus 1 year"
  ExpiresDefault "access plus 1 month"
</IfModule>
## EXPIRES CACHING ##

# BEGIN WordPress
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Then, press ctrl-x, type y, and return to save.

Finally, the default apache2 webpage needs to be disabled. Navigate to the following folder and execute the following commands:

cd /etc/apache2/sites-available
sudo a2dissite 000-default.conf
sudo systemctl reload apache2
sudo systemctl restart apache2

With these changes in place, it is necessary to reboot the ECP instance to ensure these changes take effect. To reboot the ECP instance, enter the following command:

sudo /sbin/reboot

Exit from either terminal (Mac OS) or PuTTY (Windows), and wait several minutes for the reboot to complete and everything to update. At this point, access the website from any browser, as indicated below, and check for the following:

  • Access using ‘https://seattlehobbies.com‘ and verify website appears and address bar shows the ‘https://seattlehobbies.com ‘ address along with the padlock symbol.
  • Access using ‘http://seattlehobbies.com ‘ and verify website appears and address bar shows the redirected ‘https://seattlehobbies.com ‘ address along with the padlock symbol.
  • Access using ‘https://www.seattlehobbies.com ‘ and verify website appears and address bar shows the redirected ‘https://seattlehobbies.com ‘ address along with the padlock symbol.
  • Access using ‘http://www. seattlehobbies.com ‘ and verify website appears and address bar shows the redirected ‘https://seattlehobbies.com ‘ address along with the padlock symbol.

If these tests for https access and redirection are successful, then access each page on the website and look for the padlock symbol in the address bar. The padlock symbol in the address bar indicates that the webpage is fully secured. It only takes one nonsecure item link on the webpage to disable the padlock symbol. If the padlock symbol appears in the address bar for each page on the website, we are done. If there are web pages that do not display the padlock symbol in the address bar, then use Why No Padlock? to identify the specific reasons (e.g., accessing an image using http instead of https). Fix the identified reasons on each webpage to get the padlock in the address bar.

Conduct Speed Tests for each Webpage

It is informative to run a speed test on webpage access, starting with the home page for the website. I especially like Pingdom because it breaks down access times for each item (e.g., css files, javascript files, fonts, images). The report and, especially, the detailed time plots provide an amazing amount of useful information regarding access times. Optimizing website performance is beyond this tutorial series.

Summary

This six-part series on setting up a WordPress site on AWS using an EC2 instance (Ubuntu 20.04) with a LAMP stack results in a very cost-effective WordPress website hosting solution.

Reference Material

Certbot Installation Guide

Getting Started with Let’s Encrypt

SSL Labs

Why No Padlock?

Pingdom