Install Nginx PageSpeed Module on Ubuntu 22.04/20.04 Server

ngx_pagespeed is an open-source Nginx module that automatically applies best practices to optimize website front-end performance. In this tutorial, I will be showing you how to install PageSpeed module with Nginx on Ubuntu 22.04 and Ubuntu 20.04 server. We are going to compile ngx_pagespeed as a dynamic module, which will simplify ongoing maintenance.

Step 1: Install Nginx Web Server on Ubuntu

sudo apt install nginx

PageSpeed integrates with Nginx as a dynamic module, which allows you to compile source code of individual modules without compiling Nginx itself.

The Nginx binary needs to be compiled with the --with-compat argument, which will make dynamic modules binary-compatible with your existing Nginx binary. However, not every Nginx binary shipped from the default Debian/Ubuntu repository is compiled with the --with-compat argument.

Check the configure arguments of Nginx with the following command:

sudo nginx -V
Nginx-binary-configure-with-compat

Now we need to enable source code repository, so we will be able to download Nginx source code.

Ubuntu

sudo apt install software-properties-common
sudo apt-add-repository -ss
sudo apt update

Note: PageSpeed Module currently isn’t compatible with Nginx 1.23.0. I don’t recommend installing the latest version of Nginx. The nginx package from the default Ubuntu repository is fine.

Step 2: Download Nginx Source Package

Run the following command to make a nginx directory under /usr/local/src/ to store the Nginx source code package. Replace username with your real username.

sudo chown username:username /usr/local/src/ -R 

mkdir -p /usr/local/src/nginx

cd into the Nginx source directory.

cd /usr/local/src/nginx/

Download Nginx source package with the command below:

sudo apt install dpkg-dev

sudo apt source nginx

If you see the following warning message, you can safely ignore it.

W: Download is performed unsandboxed as root as file 'nginx_1.19.5-0ubuntu1.dsc' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)

Check out the downloaded files.

ls

Sample output:

nginx-1.19.5
nginx_1.19.5-1~bionic.debian.tar.xz
nginx_1.19.5-1~bionic.dsc
nginx_1.19.5.orig.tar.gz

Step 3: Download ngx_pagespeed Source Package

To compile Nginx with ngx_pagespeed module, we also need ngx_pagespeed source package. Clone the ngx_pagespeed Git repository.

cd /usr/local/src

sudo apt install git

git clone https://github.com/apache/incubator-pagespeed-ngx.git

cd incubator-pagespeed-ngx/

Use the latest-stable branch.

git checkout latest-stable

Let’s take a look at the PSOL_BINARY_URL file.

cat PSOL_BINARY_URL

We can see the PSOL (PageSpeed Optimization Libraries) download URL.

https://dl.google.com/dl/page-speed/psol/1.13.35.2-$BIT_SIZE_NAME.tar.gz

Download PSOL and extract it.

wget https://dl.google.com/dl/page-speed/psol/1.13.35.2-x64.tar.gz
tar xvf 1.13.35.2-x64.tar.gz

It will create a psol directory under incubator-pagespeed-ngx directory.

Step 4: Compile  ngx_pagespeed Module

Make sure you are in the Nginx source directory.

cd /usr/local/src/nginx/nginx-1.19.5

Install build dependencies for Nginx.

sudo apt build-dep nginx
sudo apt install uuid-dev libpcre2-dev

Configure the environment with the following command. We will not compile Nginx itself, but compile the PageSpeed module only. The --with-compat flag will make the module binary-compatible with your existing Nginx binary.

sudo ./configure --with-compat --with-openssl=/usr/include/openssl --add-dynamic-module=/usr/local/src/incubator-pagespeed-ngx

Build the PageSpeed modules only, which will be finished in just a few moments.

sudo make modules

If your encounter errors, check if your server has enough RAM. The module will be save as objs/ngx_pagespeed.so, copy it to the /usr/share/nginx/modules/ directory.

sudo cp objs/ngx_pagespeed.so /usr/share/nginx/modules/

If you installed Nginx from nginx.org repostiory, you can copy it to /etc/nginx/modules/ directory instead.

sudo cp objs/ngx_pagespeed.so /etc/nginx/modules/

Step 5: Load the ngx_pagespeed Module

Edit the main Nginx configuration file.

sudo nano /etc/nginx/nginx.conf

Add the following line at the beginning of the file.

load_module modules/ngx_pagespeed.so;

Save and close the file. Then test Nginx configuration.

sudo nginx -t

If the test is successful, reload Nginx.

sudo systemctl reload nginx

Step 6: Configure PageSpeed Filters

Create a folder for pagespeed caches and change its ownership to Nginx user (www-data) so that it can be written by Nginx.

sudo mkdir -p /usr/share/nginx/ngx_pagespeed_cache

sudo chown -R www-data:www-data /usr/share/nginx/ngx_pagespeed_cache

Now edit Nginx server block config file.

sudo nano /etc/nginx/conf.d/your-domain.conf

Add the following pagespeed directives in server section.

# enable pagespeed module on this server block
pagespeed on;
pagespeed Domain https://www.example.com;
pagespeed Domain https://example.com;

# uncomment the following line if your website runs on HTTPS protocol
#pagespeed FetchHttps enable;

#admin console
pagespeed Statistics on;
pagespeed StatisticsLogging on;
pagespeed LogDir /var/log/pagespeed;
pagespeed AdminPath /pagespeed_admin;

location ~ ^/pagespeed_admin {
   allow 127.0.0.1;
   allow your-own-IP-address;
   deny all;
}

# Needs to exist and be writable by nginx. Use tmpfs for best performance.
pagespeed FileCachePath /usr/share/nginx/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$" { }

pagespeed RewriteLevel CoreFilters;

If you host multiple websites on a single server, add the above pagespeed directives to each server block config file to enable pagespeed on each of them.

The last directive set CoreFilters as the rewrite level. PageSpeed offers 3 rewrite levels: CoreFilter, PassThrough and OptimizeForBandwidth. CoreFilter is the default as it contains filters that are considered safe for most websites.

CoreFilter contains the following filters.

  • add_head: Adds a <head> element to the document if not already present.
  • combine_css: Combines multiple CSS elements into one.
  • combine_javascript: Reduce the number of HTTP requests made by a browser during page refresh by replacing multiple distinct JavaScript files with a single one.
  • convert_meta_tags: Adds a response header that matches each meta tag with an http-equiv attribute.
  • extend_cache: Extends cache lifetime of CSS, JS, and image resources that have not otherwise been optimized, by signing URLs with a content hash.
  • fallback_rewrite_css_urls: Rewrites resources referenced in any CSS file that cannot otherwise be parsed and minified.
  • flatten_css_imports: Inline CSS by flattening all @import rules.
  • inline_css: Inlines small CSS files into the HTML document.
  • inline_import_to_link: Inlines <style> tags comprising only CSS @imports by converting them to equivalent <link> tags.
  • inline_javascript: Inlines small JS files into the HTML document.
  • rewrite_css: Rewrites CSS files to remove excess whitespace and comments, and, if enabled, rewrite or cache-extend images referenced in CSS files. In OptimizeForBandwidth mode, the minification occurs in-place without changing URLs.
  • rewrite_images: This is a filter group that includes inline_images, recompress_images, convert_to_webp_lossless, and resize_images.
  • rewrite_javascript: Rewrites JavaScript files to remove excess whitespace and comments. In OptimizeForBandwidth mode, the minification occurs in-place without changing URLs.
  • rewrite_style_attributes_with_url: Rewrite the CSS in style attributes by applying the configured rewrite_css filter to it.

You may also want to add the following PageSpeed directives in Nginx server block config file that is not in CoreFilters.

pagespeed EnableFilters collapse_whitespace;
pagespeed EnableFilters lazyload_images;
pagespeed EnableFilters insert_dns_prefetch;
pagespeed EnableFilters prioritize_critical_css;
#This filter is likely to cause problems for loading your web pages. 
pagespeed EnableFilters defer_javascript;

Note that WordPress now lazy-load images by default. So if you use WordPress, you don’t need to enable the lazyload_images filter.

For a detailed explanation of each filter, go to Google PageSpeed Filter page.

Save and close your server block config file. To generate webp images, I recommend installing the following packages.

sudo apt install imagemagick php7.4-imagick ffmpeg

Before Reloading Nginx, I recommend going to Google PageSpeed Insights to test your webpage. Then reload Nginx.

sudo systemctl reload nginx

Now test your PageSpeed score again, so you can see the difference.

Step 7: Check if ngx_pagespeed is Working

Go to your website. Refresh a few times then check your page source. Hit Ctrl+F key and search pagespeed. You will see that many of your website resource has been processed by pagespeed. Some CSS files and javascript files are combined into one file. If you use the Google Chrome browser, you will see that the picture of your website is in webp file format. webp can greatly reduce image file size. For example, the size of the main image file on my home page is reduced from 208KB to 98KB.

You can also find ngx_pagespeed is working by comparing your website speed test. Also on your server, you can issue the following command:

curl -I -p https://youdomain.com

You will see X-Page-Speed and its version number.

x-page-speed: 1.13.35.2-0

Troubleshooting Tips

Image was not converted to webp format

If your PageSpeed filters are not working, then you can open the page source code in your web browser, and append the ?PageSpeedFilters=+debug parameter to the URL to show debug information, which tells you why a resource was not optimized by PageSpeed module.

For example, some folks might see the following error.

<!--The preceding resource was not rewritten because its domain (www.example.com) is not authorized-->

This is because the domain is not added to the allowed list. You can add domain like below to the allowed list in the Nginx configuration file.

pagespeed Domain https://www.linuxbabe.com;
pagespeed Domain https://linuxbabe.com;

A good way to check PageSpeed debug message is to search the phrase “was not rewritten because“.

If PageSpeed still doesn’t seem to be working and you don’t see debug information in the source code, refresh the page a few more time.

Image failed to load

If the image on your web page failed to load in web browser and you see the following error message in your web server log, then you need to add the pagespeed FetchHttps enable; directive in Nginx configuration file to make the PageSpeed module fetch HTTPS resources directly, without going to HTTP first.

Resource based on http://www.example.com/path/to/png but cannot access the original

I also recommend adding the following custom DNS entries in the /etc/hosts file, so the PageSpeed module don’t have to query public DNS to resolve your domain name.

127.0.0.1 localhost example.com www.example.com

::1 ip6-localhost ip6-loopback example.com www.example.com

If there are still images failed to load, you can enable LoadFromFile for PageSpeed. This allows PageSpeed to fetch static files directly from the local disk/directory. Add the following line in your Nginx configuration file. Replace /usr/share/nginx/example.com with the web root directory of your website.

pagespeed LoadFromFile "http://www.example.com" "/usr/share/nginx/example.com";

FATAL:shared_mem_cache.cc(564)] Check failed: worker != NULL.

This error can occur when you enable PageSpeed on multiple Nginx virtual hosts. The best practice is to use the same PageSpeed configuration across all your Nginx virtual hosts.

This error can be found in the /var/log/nginx/error.log file. It will cause one of Nginx woker process to exit.

worker process 755743 exited on signal 6

Hold Nginx from Being Automatically Upgraded

If a newer version of Nginx is available in the repository, the sudo apt upgrade command will upgrade Nginx. The newer version of Nginx is not going to be compatible with the previously compiled PageSpeed module. If Nginx is upgraded by the sudo apt upgrade command, it will fail to restart.

My advice is to prevent Nginx from being upgraded when you run sudo apt upgrade command. This can be achieved by the following command:

sudo apt-mark hold nginx

When apt package manager tells you that a new version of Nginx is available, you should download the new Nginx source package and compile the PageSpeed module again. Move the newly-compiled PageSpeed module to /usr/share/nginx/modules/ or /etc/nginx/modules/ directory. Basically that means you need to remove everything under /usr/local/src/ directory (sudo rm /usr/local/src/* -rf ) and go through step 2, step 3 and step 4 again.

Then unhold Nginx.

sudo apt-mark unhold nginx

And upgrade Nginx.

sudo apt upgrade nginx

Once the upgrade is complete, hold Nginx again.

sudo apt-mark hold nginx

To show what packages are hold, run

apt-mark showhold

Improving Nginx PageSpeed Performance

The PageSpeed module can use lots of CPU resources when it’s doing the grunt work. For better performance, you should use at least 4 CPU cores, otherwise your web pages may feel slower when the PageSpeed module is enabled.

A good way to reduce CPU load is to change the default RewriteLevel to PassThrough, which disables all PageSpeed filters. Then you can enable the filter you need, such as

pagespeed EnableFilters convert_to_webp_lossless;
pagespeed EnableFilters convert_jpeg_to_webp;
pagespeed EnableFilters resize_images;

Pre-Processing

A web page can take several refreshes before its fully optimized by the PageSpeed module. If you want to serve fully optimized web pages to visitors, you can use the following command to pre-processing all web pages on your website.

wget -m -p -E -k -P /tmp/ramdisk/ https://www.example.com/

This command will fetch all web pages on your website and you can create a Cron job for this command to run hourly, so PageSpeed can fully optimize your web pages before you roll it out to production.

PageSpeed & Nginx FastCGI Cache

Can the PageSpeed module work with Nginx FastCGI cache? Yes.

When a browser sends an HTTP request to your website, Nginx will first check if the FastCGI cache exists for the requested web page.

  • If the cache is not found, Nginx will send requests to PHP-FPM, which translates PHP code to static HTML code and send it back to Nginx. Then the PageSpeed module will optimize the HTML web page and send it to the web browser.
  • If the cache is found, the PageSpeed module will optimize the cached page and send it to the web browser.

PageSpeed & Cloudflare Static HTML Cache

Can the PageSpeed module work with Cloudflare static HTML cache? Yes.

However, keep in mind that it can take several refreshes before PageSpeed can fully optimize your web pages. If your web pages appear to be not optimized, clear the Cloudflare static HTML code several times.

Next Step

I hope this tutorial helped you install PageSpeed module with Nginx on Ubuntu 22.04 and Ubuntu 20.04. You may also want to set up the ModSecurity web application firewall to protect your website from hacking.

And as always, if you found this post useful, then subscribe to our free newsletter for more tips and tricks 🙂

Rate this tutorial
[Total: 8 Average: 4.9]

19 Responses to “Install Nginx PageSpeed Module on Ubuntu 22.04/20.04 Server

  • Thanh Tung
    4 years ago

    This post is very useful. Thank you so much 🙂

  • Don’t work thanks

  • thank you for your great post . i’m using webinoly , their structure are little different . how we can install on this kind of lemp installation

  • Thanks, this is the only way to install pagespeed in u18 that works for me.

  • There are a handful of tutorials explaining how to install pagespeed with nginx. This is the BEST one.

    There is no need to compile nginx itself!

  • Thanks

  • Hmm does not work for me. I’m using Ubuntu 20.04.1 LTS.

    Apt installs nginx 1.18 while the source gets 1.17

    In the end when the module is built I get:

    nginx: [emerg] module “/usr/share/nginx/modules/ngx_pagespeed.so” version 1017010 instead of 1018000 in /etc/nginx/nginx.conf:1

    Looks like the module is being built against the source (1.17) and not towards the binary version (1.18)?

    • Xiao Guoan (Admin)
      2 years ago

      When a new version of Nginx is available, you should download the new Nginx source package and compile the PageSpeed module again.

      • Hey Xiao, thanks for the reply!

        When I did

        apt install

        with the normal Ubuntu repo (focal main restricted), I sort of was expecting that if I enabled the dev-src, the nginx versions would at least match (seems to not be the case)

        Can I select a specific branch of nginx somehow so that the source and binaries would match?

  • Xiao Guoan (Admin)
    2 years ago

    If you run sudo nginx -t and see the following warning.

    nginx: [warn] conflicting server name "example.com" on [::]:443, ignored
    nginx: [warn] conflicting server name "example.com" on 0.0.0.0:443, ignored
    

    it means there are two virtual host files that contains the same server_name configuration. Don’t create two virtual host files for one website, or PageSpeed might not work.

  • Yannis Sintos
    1 year ago

    I run the whole procedure, but after finishing it, it doesn’t fetch any css on the page and I see a stripped page.
    Anyone can help with that ?

  • Hello, I wonder if you still monitoring this tutorial? I configured the ngx_pagespeed mod and have it running but I am not converting new uploaded images to webp format. Before I used Imagify and switched to the mod about a week ago. I have read so many writings but is not getting the solution. Any suggestions?

    Thanks, Fred

  • Hey Linuxbabe. You have a small error that I wanted to point out.
    In your notes, you declare that users should install the Mainline repository (PPA) of ondrej.
    Also, in your sources.list.d folder, you show that you are using

    ondrej-ubuntu-nginx-mainline-*.list

    However, your first command

    sudo add-apt-repository ppa:ondrej/nginx -y

    ,
    demonstrates that you are installing the stable version of the Ondrej Nginx repository. You should correct your first command to look like this, in order to reflect the installation of the mainline repo…

    sudo add-apt-repository ppa:ondrej/nginx-mainline

    Just trying to help.

    • Xiao Guoan (Admin)
      3 months ago

      I prefer to use the Nginx stable version now, instead of the mainline version.

    • Xiao Guoan (Admin)
      2 months ago

      Actually, I just updated this article to use the nginx package from the default repository. Using the latest version has two drawbacks:

      1. It can introduce incompatibility with Nginx PageSpeed.
      2. You will spend more time updating the PageSpeed module if you use the latest version of Nginx. The nginx package from the default repository only updates to address security problems.

      • Danran
        1 week ago

        These are good things to know. I am switching from the mainline repo on nginx.org, to the stable repo on nginx.org, and building my own modules for each update. What is the difference between the debian stable repo packages, and the nginx.org stable repo packages? Do the nginx.org stable repo’s have incompatiblity issues with pagespeed, or is it just the nginx.org mainline repos?

      • Hi Xiao,

        Thanks for these guides. Tremendously helpful.

        An issue I have is that if I follow up this guide with How to Set Up ModSecurity with Nginx on Debian/Ubuntu I run into an issue with the section How to Use Brotli with ModSecurity in Nginx. If I try to install libnginx-mod-brotli from ondrej/nginx or ondrej/nginx-mainline (I have tried both, making sure to purge existing installations and start over) it has a dependency on either nginx-1.22-* (stable) or nginx-1.23-* (mainline) which opens other cans of worms such as PageSpeed/psol issues with both. I can overcome these issues by following recommended alternative methods from various repo issue posts but in the interests of not wanting to deal with these issues every time mainline is updated I’m wondering if there is an alternative method to installing libnginx-mod-brotli that works with nginx-1.18 (Ubuntu 22.04).

  • Danran
    1 week ago

    Great tutorial! I’ve looked over all of the github repositories for multiple modules including this one and modsecurity, and no where to be found are instructions to add

    --with-openssl=/usr/include/openssl

    to the

    ./configure
     command. Could you please explain (to help me understand), exactly what the 
    --with-openssl=/usr/include/openssl

    argument is for and what it does? Thanks!

    • Danran
      1 week ago

      Great tutorial! I’ve looked over all of the github repositories for multiple modules including this one and modsecurity, and no where to be found are instructions to add

      --with-openssl=/usr/include/openssl

      to the

      ./configure

      command. Could you please explain (to help me understand), exactly what the

      --with-openssl=/usr/include/openssl

      argument is for and what it does? Thanks!

Leave a Comment

  • Comments with links are moderated by admin before published.
  • Your email address will not be published.
  • Use <pre> ... </pre> HTML tag to quote the output from your terminal/console.
  • Please use the community (https://community.linuxbabe.com) for questions unrelated to this article.
  • I don't have time to answer every question. Making a donation would incentivize me to spend more time answering questions.

The maximum upload file size: 2 MB. You can upload: image. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here