Optimize websites using Nginx PageSpeed Dynamic Module

What is Google PageSpeed?

Pagespeed is a set of modules that designed to help optimize websites and performance by applying optimization to pages and static assets such as minifying stylesheets, javascript, images recompression and HTML files thus, improve page performance. Google's PageSpeed Insight is a tool to help analyze website and suggest an improvement based on results.

Pagespeed module can be built to be use with Apache and Nginx webserver, however this post shows how to use with Nginx webserver.

To use the Pagespeed with Nginx, you have two options, either:

  1. Compile and build Nginx package with support for PageSpeed, then compile PageSpeed. Or,
  2. Compile PageSpeed as a dynamic module to be use with Nginx.

In the first option, I not really recommend because when you build the Nginx package from source, it also means if there is an update, you need to redo the whole things with the new updated package. And also you have to keep in mind to hold the build from apt, to prevent automatic update and lost your current build.

The second option, we just build the PageSpeed dynamic module and load them with Nginx. If new PageSpeed module comes in, we just have to build the module itself only and not disturbing your current Nginx or configuration. Or if Nginx push a new update, you need to re-build the module to be compatible with the newer version.

Make sure you're using Nginx version 1.11.5 and later to do this because older version doesn't support --with-compat option when configure the module. If you're using nginx older than this, then I suggest to use Nginx pre-built package from mainline version as it has more features than stable release.

Either of the options above, I suggest you to built this module on dev machine. So that if you break the setup, it doesn't break your current system. Make sure your dev machine are same as the production machine, by that means the OS and version are need to be same. Here, I'm using Ubuntu 16.04 as example.

This guide is based on Google's manual install instruction. I'm going to show you how to build nginx pagespeed module to be used with Nginx web server.

Steps

I made a simple script here to help automate the process. The script is still in experimental, use with cautious!. Else, follow the steps below:

  1. Update your system packages, to make sure you download the latest version of required software.
sudo apt update
  1. Install Nginx and build dependency. This is required to build the module.
sudo apt-get install build-essential uuid-dev unzip gcc make libpcre3 libpcre3-dev zlib1g-dev nginx -y
  1. Get Nginx version number. Make sure your Nginx version is 1.11.5 or later. If your Nginx version is not compatible, you can try using Nginx Mainline repository.
nginx -v
  1. Download Nginx source from web.
wget http://nginx.org/download/nginx-{your-version-number}.tar.gz
  1. Get the latest version number pagespeed module at https://modpagespeed.com/doc/release_notes
  2. Download the latest version ngx_pagespeed module at github and extract it. https://github.com/apache/incubator-pagespeed-ngx/archive/v{ngx_pagespeed_module_version}-stable.zip
  3. Change directory to incubator-pagespeed and download PageSpeed Optimization Library (psol). https://dl.google.com/dl/page-speed/psol/{ngx_pagespeed_module_version}-x64.tar.gz
  4. Run the following command. Replace ${NPS_VERSION} with your ngx_pagespeed version above.
cd incubator-pagespeed-ngx-${NPS_VERSION}-stable/
psol_url=https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}-x64.tar.gz
[ -e scripts/format_binary_url.sh ] && psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL)
wget -q ${psol_url}
tar -xzf $(basename ${psol_url})  # extracts to psol/
rm -r $(basename ${psol_url})
  1. Change directory to Nginx source folder and compile the Pagespeed Dynamic module. Run the configure script with the --with-compat argument to make the dynamic module binary‑compatible with Nginx. Then run make modules to compile just the module.
./configure --add-dynamic-module=../incubator-pagespeed-ngx-{ngx_pagespeed_module_version}-stable --with-compat
make modules

After done make, the object module are available in folder obj/ngx_pagespeed.so. This module now can be transfer to production server.

Folder structure

Now you need to copy the module to a folder then load them in a config file. Different distribution may have different nginx module folder, modules-available and modules-enabled directory. Some put in /usr/share/nginx/modules, /usr/lib/nginx/modules or even /etc/nginx/modules. Check those directories and symlinks if available.

My distribution has the following structure: (x links to y)

/etc/nginx/modules -> /usr/lib/nginx/modules -> /usr/share/nginx/modules
/etc/modules-enabled -> /usr/share/nginx/modules-available

The nginx folder structure symlinked to other directories makes changes a bit confusing. What I do is gather all modules together in one place in /etc/nginx/modules (no symlinks) and remove any trace folder such in /usr/share/nginx/modules or /usr/lib/nginx/modules.

  1. If you don't have the folder structure like above, create new directory as below. These are the folder structure you need to have (as what I do):
/etc/nginx/modules           # This is where you placed all your modules (.so file)
/etc/nginx/modules-available # Here where you create a conf file and link to the module
/etc/nginx/modules-enabled   # Symlink any module(s) from `/etc/nginx/modules-available` you want to enable in this folder
  1. Copy the ~/nginx-{your-version}/objs/ngx_pagespeed.so to /etc/nginx/modules/ngx_pagespeed_{ngx_pagespeed_version}.so. I suggest to append the ngx_pagespeed_version at the module, so if the newer version comes, you know to identify the module version.

  2. Create /etc/nginx/modules-available/ngx_pagespeed.conf file and place this in the configuration. The 'load_module' directives is used to load the PageSpeed as a dynamic module.

# rename your ngx_pagespeed version!
load_module /etc/nginx/modules/ngx_pagespeed_1.13.35.2.so;
  1. To enable the module, symlink the /etc/nginx/module-available/ngx_pagespeed.conf to /etc/nginx/modules-enabled/ngx_pagespeed.conf.
sudo ln -s /etc/nginx/module-available/ngx_pagespeed.conf /etc/nginx/modules-enabled/ngx_pagespeed.conf
  1. Check in the nginx.conf, make sure to load all modules from /etc/nginx/modules-enabled/*.conf. If not, place this at the top‑level ("main") context of the nginx.conf configuration file (that is, not in the http or stream contexts).
include /etc/nginx/modules-enabled/*.conf;
  1. What ever you do, make sure you have load the module in nginx configuration. Check everything if syntax is okay:
sudo nginx -t

If everything is good, you've successful load the module with Nginx! Proceed to configuration.

Configuration

  1. Create a folder name 'snippets' in /etc/nginx/. In this folder, we will put our pagespeed configuration file here, and will be include in virtual host conf.
sudo mkdir /etc/nginx/snippets

These are the configuration that we're going to use for the pagespeed module. You can refer here for more info. Place this in /etc/nginx/snippets/pagespeed.conf.

    ## pagespeed module ##
    pagespeed on;
    
    # Honoring Content-Security-Policy Headers
    pagespeed HonorCsp on;

    # Lower-casing HTML element and attribute names
    pagespeed LowercaseHtmlNames on;

    # Pagespeed Header
    pagespeed XHeaderValue "Powered By ngx_pagespeed"; 

    # Needs to exist and be writable by nginx.  Use tmpfs for best performance.
    pagespeed FileCachePath /var/ngx_pagespeed_cache;

    # Ensure requests for pagespeed optimized resources go to the pagespeed handler
    # and no extraneous headers get set.
    location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" {
       add_header "" "";
    }
    location ~ "^/pagespeed_static/" { }
    location ~ "^/ngx_pagespeed_beacon$" { }

Include to Virtual Host

After done writing the pagespeed.conf snippet, go to sites-enabled folder and open your site conf. In server block or http block, include the snippet to the configuration. If you have multiple sites enabled, you must include this to every sites configuration to enable pagespeed on every sites.

include /etc/nginx/snippets/pagespeed.conf;

Validate

Check if all the configurations are correct. If everything is okay, restart nginx service to load the PageSpeed module into the running instance.

sudo nginx -t
sudo service nginx restart

Check if Pagespeed is running by using the curl command:

$ curl -I https://www.metahackers.pro 
HTTP/2 200 
date: Mon, 30 Apr 2018 00:46:54 GMT
content-type: text/html; charset=utf-8
set-cookie: __cfduid=d42ff6730fdae50d33c6d3f29a2c593231525049214; expires=Tue, 30-Apr-19 00:46:54 GMT; path=/; domain=.metahackers.pro; HttpOnly; Secure
x-powered-by: Express
x-frame-options: SAMEORIGIN
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
referrer-policy: strict-origin-when-cross-origin
x-page-speed: Powered By ngx_pagespeed
cache-control: max-age=0, no-cache
strict-transport-security: max-age=15552000; includeSubDomains; preload
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
server: cloudflare
cf-ray: 4135fe768d0c110b-SIN

It should have output the X-page-speed header. Also check Pagespeed Insights for website performance test. PageSpeed Insights is a seperate tool from Google to test website performance and level of optimization for both desktop and mobile devices. It is a handy tool for measuring your site and for indicate the efficacy of the PageSpeed module.

You can use PageSpeed Insights to compare your site score and recommendation for optimization with and without PageSpeed enabled. Swap between the pagespeed on; and pagespeed off; directives to measure the effectiveness of the PageSpeed module on your site.

PageSpeed applies its optimizations without any further configuration or tuning. However, if you want to have more control over which optimizations are performed on your site, refer to the PageSpeed documentation.