How to run Ultra-Fast WordPress on Http/2 with ALPN, WP-Rocket and AWS CloudFront on AWS and RHEL

Computing

Introduction

A website is a mirror of his/her owner. If one’s website is too slow, maybe the owner does not care about pushing the limits in all his/her other endeavors.

The steps below outline the instructions how to set up the one of the fastest possible WordPress installations at the moment.

Disclaimers

  • Neither AWS, nor RedHat does provide any support for these installation steps. If you require support, contact Jiri to discuss his availability.
  • These instructions are a result of years of experience, extensive web research and countless conversations with various brilliant people. Their help is much appreciated.
  • The packages discussed below are cutting-edge, and they are not yet part of RedHat Enterprise Linux (RHEL) or AWS Linux. If you prefer, you can download them already built from either Remi’s Repo or Webtatic provided you trust these repositories. For production environments, I strongly advise against that due to a chance of trojan horses etc. being included in the built versions.

Target Infrastructure

I build all my systems on AWS because I found their level of service unmatched by services of any other cloud provider.

I use RedHat Enterprise Linux because

  • it’s well supported
  • it’s a stabilized version of Fedora Linux and some time ahead of the default AWS Linux
  • I can easily test the installation steps on a local dev machine with VMWare Workstation’s RHEL image with snapshots which I found to be the most effective ways of fine-tuning production systems

The below instructions should apply with minor modifications to other Linux versions.

Http/2

Http/2 is a performance boosting update to the 1999’s http 1.1 protocol used for all web traffic.

In a nutshell, it utilizes only a single multiplexed connection to the server (opening of a connection channel takes most of the web page loading time), it’s binary, it prioritizes the order of resources being delivered, and pushes to the client pro-actively the resources it may request in the future.

It’s already supported by majority of web browsers – at the time of writing this article in January 2017 it was 78%.


Thus, by your website not supporting the protocol, your audience spends unnecessarily more time on its loading, and in consequence being less satisfied.

OpenSSL, Apache, PHP Setup

0. Set Up RedHat

Enable RedHat Repositories:

sudo yum update -y
sudo su
cp /etc/yum.repos.d/redhat-rhui.repo /home/ec2-user
vi /etc/yum.repos.d/redhat-rhui.repo

Change enabled=0 to enabled=1

Install the prerequisites:

yum install -y mc mlocate at wget links perl gcc  
yum groupinstall "Development Tools" -y
yum install -y autoreconf automake autoconf pcre-devel openssl-devel git wget mlocate

1. Upgrade OpenSSL

cd /usr/local/src
wget https://www.openssl.org/source/openssl-1.0.2-latest.tar.gz
tar -zxvf openssl-1.0.2-latest.tar.gz
cd openssl-1.0.2j
./config --prefix=/usr --openssldir=/usr/local/openssl shared
make
make test
make install

2. Apache

# Install nghttp2
cd /usr/local/src
git clone https://github.com/nghttp2/nghttp2
cd nghttp2
git submodule update --init
autoreconf -i
automake
autoconf
./configure
make
make install

# Install Apache
cd /usr/local/src/
wget http://www-us.apache.org/dist//httpd/httpd-2.4.25.tar.gz
tar -zxvf httpd-2.4.25.tar.gz 
cd httpd-2.4.25
cd srclib
wget http://www-us.apache.org/dist//apr/apr-1.5.2.tar.gz
tar xvf apr-1.5.2.tar.gz 
mv apr-1.5.2 apr
wget http://www-us.apache.org/dist//apr/apr-util-1.5.4.tar.gz
tar xvf apr-util-1.5.4.tar.gz 
mv apr-util-1.5.4 apr-util
cd /usr/local/src/httpd-2.4.25
./configure --prefix=/opt/httpd --enable-http2 --with-nghttp2=/usr/local/lib  --enable-so
make 
make install

cp /opt/httpd/conf/httpd.conf  /home/ec2-user
vi /opt/httpd/conf/httpd.conf

Uncomment these lines

LoadModule http2_module modules/mod_http2.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
Include conf/extra/httpd-ssl.conf

Add these lines

<IfModule http2_module>
    LogLevel http2:info
</IfModule>

Protocols http/1.1 h2 h2c
H2MaxSessionStreams 10
H2MaxWorkerIdleSeconds 15
H2MaxWorkers 15
H2MinWorkers 5

Change Override None to Override All

Backup SSL settings

cp /opt/httpd/conf/extra/httpd-ssl.conf  /home/ec2-user
vi /opt/httpd/conf/extra/httpd-ssl.conf

Change these values for these parameters:

  • ServerName
  • ServerAdmin

Uncomment the parameter SSLCertificateChainFile.

Upload the SSL certificates to the appropriate locations

SSLCertificateFile "/opt/httpd/conf/server.crt"
SSLCertificateKeyFile "/opt/httpd/conf/server.key"
SSLCertificateChainFile "/opt/httpd/conf/server-ca.crt"

Restore permissions

restorecon -RvF /opt/httpd/conf

Reboot, log back in and check all apache configs are fine

/opt/httpd/bin/apachectl configtest

Set up auto-start of Apache

touch /etc/init.d/apache2
chmod 755 /etc/init.d/apache2
vi /etc/init.d/apache2

Paste there this text:

#!/bin/bash
#
# apache2        Startup script for the Apache HTTP Server
#
# chkconfig: 3 85 15
# description: Apache is a World Wide Web server.  It is used to serve \
#              HTML files and CGI.
 
/opt/httpd/bin/apachectl $@

Run

chkconfig --add apache2
chkconfig --list apache2

Set up permissions for www

sudo groupadd www
sudo usermod -a -G www ec2-user
sudo chown -R root:www /opt/httpd/htdocs
sudo chmod 2777 -R /opt/httpd/htdocs

Reboot to see if the Apache was started automatically

3. PHP

sudo su
yum install -y perl libxml2-devel curl-devel libpng-devel
cd /usr/local/src
wget http://php.net/get/php-7.1.0.tar.gz/from/this/mirror
mv mirror php-7.1.0.tar.gz
tar -zxvf php-7.1.0.tar.gz
cd php-7.1.0
./configure --enable-bcmath --enable-mbstring --with-gd  --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --includedir=/usr/include --prefix=/opt/php71 --with-apxs2=/opt/httpd/bin/apxs  --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-curl --with-zlib --enable-zip
make 
make test
make install
 
vi /opt/httpd/conf/httpd.conf

Uncomment

LoadModule php7_module modules/libphp7.so

Add

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>
 
<FilesMatch "\.phps$">
    SetHandler application/x-httpd-php-source
</FilesMatch>

Set up PHP’s settings

vi /etc/php.ini

Paste there this text

; Maximum amount of memory a script may consume (128MB)
; http://php.net/memory-limit
memory_limit = 2048M

; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
upload_max_filesize = 200M
post_max_size = 200M

log_errors=true
error_log=/opt/httpd/logs/php-errors.log

Install ImageMagick

sudo yum install ImageMagick
cp /etc/ImageMagick/policy.xml  /home/ec2-user
vi /etc/ImageMagick/policy.xml

Add there these policies, if they are not already present

<policy domain="coder" rights="none" pattern="EPHEMERAL" />
<policy domain="coder" rights="none" pattern="URL" />
<policy domain="coder" rights="none" pattern="HTTPS" />
<policy domain="coder" rights="none" pattern="MVG" />
<policy domain="coder" rights="none" pattern="MSL" />
<policy domain="coder" rights="none" pattern="TEXT" />
<policy domain="coder" rights="none" pattern="SHOW" />
<policy domain="coder" rights="none" pattern="WIN" />
<policy domain="coder" rights="none" pattern="PLT" />

Reboot and restore the original WordPress site from BackupBuddy.

4. Final Check

Go to https://tools.keycdn.com/http2-test and check your website does run on Http/2 with ALPN:

WordPress Setup

I highly recommend the below two WordPress plugins for enhanced WordPress performance.

In addition, I strongly recommend manual running of the WordPress’s Cron.

sudo crontab -e
* * * * * /usr/bin/php /opt/httpd/htdocs/wp-cron.php >/dev/null 2>&1

1. WP-Offload

WP-Offload is a WordPress Plugin uploading all media (images, videos and others) into an AWS S3 bucket which is then mapped onto an AWS CloudFront distribution serving as a super-fast CDN.

Recommendation: Do enable Http/2 on the AWS CloudFront Distribution.

2. WP-Rocket

WP-Rocket is one of the best page caching / pre-loading plugins available.

It minifies CSS, JS files, offers lazy loading of images or video, and stores pre-generated html pages in a cache so that whenever the web server receives a page request, it can be served without the server having to build it from its MySQL representation.

And above all, it’s exceptionally well supported.

Menu