How can you add a dynamic PageSpeed module to an already-built instance of NGINX?
For install automation, I’ve summarized the codes and minimal settings in this Bash script. This script was tested to work on the latest stable version of NGINX. If it’s your first time to compile this, feel free to execute the codes step-by-step. It will help you troubleshoot any peculiarities on your system.
You may choose to automate the installation by simply running the script above. In its default settings, it will process the version number you will pass to it. To get your NGINX’s version number run this command:
nginx -v
nginx version: nginx/1.17.1
Since the version number in this example is 1.17.1, after you have downloaded the bash script above, go to the directory where the script is and run these commands:
chmod +x mkpagespeed
./mkpagespeed 1.17.1
Building PageSpeed may take a few minutes and could be a bit resource-intensive, especially on a server with modest specs. If the script runs through errors please let me know so I may make adjustments to it.
Loading the module
To activate PageSpeed, add this line to NGINX’s main configuration file (mine was at /etc/nginx/nginx.conf
), outside any block { ... }
, on the top-most section of the config file:
load_module modules/ngx_pagespeed.so;
# http {
# ...
# }
If you are not sure what your NGINX config file path is, run this command:
nginx -V 2>&1 | grep -o 'conf-path=[^ ]*' | sed 's/conf-path=//'
Configuring filters
What PageSpeed does to your served pages and assets may be fully customized via filters. There are a plethora of configurations to choose from. A pre-selected set of default filters may be activated through:
pagespeed RewriteLevel CoreFilters;
Still, don’t we normally want to fiddle with every little bit of our configuration? Here’s what’s included in my server
block:
I also set up PageSpeed Admin Pages, which required the FileCachePath
directive to be declared with it. While the Admin Pages location
blocks can be retained inside the server
block, Admin Pages are declared within the http
block, which is outside the server
block:
Updating the module
One potential problem with dynamic modules is when NGINX automatically upgrades via a package manager (e.g. apt
, yum
, or pacman
). If you’re like me, all upgrades in my server are automated by scripts. That may cause a snag because dynamic modules are version-specific. NGINX is set not to load modules that were built for a different NGINX version. So how can PageSpeed modules automatically upgrade when NGINX makes an unattended upgrade?
The answer is to make a hook to the package manager during upgrades. In apt
this may need making two or three simple scripts:
- Hook to
apt
and call a worker script. (Alternatively, the hook could directly callmkpagespeed
and thus skip the need for a worker script.) - The worker script calls one or more build scripts to update the dynamic modules.
- Build scripts will build and install the new modules just before NGINX upgrades.
Here is how a hook file could look like in /etc/apt/apt.conf.d/
:
And the worker script could contain this:
#!/bin/bash
# Call NGINX module build scripts and pass error codes to apt hook
# Get NGINX version to upgrade to
read ngfile < <(grep '/nginx_') || exit 0
ngver=$(echo $ngfile | sed 's/-.*//' | sed 's/.*_//')
# List of build scripts to run:
/usr/local/sbin/mkpagespeed $ngver || exit $?
# /usr/local/sbin/mkbrotli $ngver || exit $?
# /usr/local/sbin/mkmodsec $ngver || exit $?
This worker should point to our build script earlier, that is, mkpagespeed
. So there, dynamic module + dynamic upgrades = chill & relax. 😎 Enjoy speed! ⚡
Brotli compression
Google has another open-source project for the next-generation compression called Brotli. If you’re interested with Brotli, you can check this post: Adding Brotli to an Already-built NGINX Instance.
13 Comments
Niels · November 17, 2019 at 4:55 pm
Hello, im trying to use the script for my website of course but i got the same error => “nginx: [emerg] module “/etc/nginx/modules/ngx_pagespeed.so” is not binary compatible in /etc/nginx/nginx.conf:1″
I all ready try to add some argument like –with-cc-opt=’-DNGX_HTTP_HEADERS’ but i got the same problem
Majal Mirasol · November 18, 2019 at 3:31 pm
Hi Niels! I’m sorry but I still don’t know why this doesn’t work on other systems. Would it be possible for you to supply us with your specific system setup?
James Botkin · July 19, 2020 at 10:05 am
Got similar problem. Not binary compatibe means the args/option isn’t the same build. here’s how I do it.
$ nginx -V
– copy all args, and see your version.
– delete all local args (which having local reference ( =tmp/BlabLa/.. ). calm down, the script reference you back what module isn’t installed.
modify mkpagespeed on line 38:
nice -n 19 ionice -c 3 bash <(curl -f -L -sS https://ngxpagespeed.com/install) -n ${ngver} -m -b ${builddir} -a ‘YOUR ARGS HERE’ -y || { echo ‘!! error with module creation, exiting…’; exit 1; }
– be sure to use ” because all args/option inside an ‘.
in your case:
nice -n 19 ionice -c 3 bash <(curl -f -L -sS https://ngxpagespeed.com/install) -n ${ngver} -m -b ${builddir} -a ‘-with-cc-opt=”-DNGX_HTTP_HEADERS”‘ -y || { echo ‘!! error with module creation, exiting…’; exit 1; }
chmod +x and Run mkpagespped
$ ./mkpagespeed yournginxversion
Then, check the moddir, is it .so. or .so.old, if .so.old, rename it to .so.
For check only:
Then load pagespeed module at nginx.conf in any outside bracket of http or server.
load_module modules/ngx_pagespeed.so;
Reload nginx configuration.
if the configuration reloaded with no error then you are good to make pagespeed on and adding another option, don’t forget to reload nginx after.
Done.
Note: if you have “–with-debug” args, just strip it off. nginx pagespeed doesn’t suppoer –with-debug, and Yes, it will produce same binary.
Majal Mirasol · July 19, 2020 at 10:11 am
Awesome solution James. Thank you. I’m sorry I haven’t paid attention on this one for so long. I’ll update this when I have time. Thanks for posting back the solution. Will be helpful to future readers. 🙂 Have a good and safe day!
solut2000 · May 31, 2020 at 3:05 pm
It works great! thx!
James Botkin · July 19, 2020 at 12:35 am
IF i run the script the way it is. the configuration will not match. return:
nginx: [emerg] module “/usr/share/nginx/modules/ngx_pagespeed.so” is not binary compatible in /etc/nginx/nginx.conf:2
IF I modify the script to get matching configuration. Pagespeed have no –with-debug option etc.
James Botkin · July 19, 2020 at 9:42 am
Now, it works!
I strip all the local defined option. With no “–with debug” agrs.
Somehow the script not renaming back from ngx_pagespeed.so.old to .so, I rename it to .so, update nginx.conf and reload it.
Also I modify the script to access pagespeed admin with .htpasswd, more simple than setup vpn or specify IP to access it.
Thanks!
Gregory · September 6, 2020 at 9:12 pm
Hello,
I can’t make it works with cloudflare and Let’s Encrypt
Beginning of my server block:
server {
listen 80;
listen [::]:80;
server_name domain.com www.domain.com;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;
# Pagespeed
pagespeed on;
pagespeed SslCertDirectory /etc/letsencrypt/live/domain.com;
pagespeed SslCertFile /etc/letsencrypt/live/domain.com/cert.pem;
pagespeed MapOriginDomain "http://domain.com" "https://www.domain.com";
# WordPress-specific configurations, change according to your domain and installation path
pagespeed LoadFromFile https://www.domain.com/wp-content/ /var/www/html/wp-content/;
pagespeed LoadFromFile https://www.domain.com/wp-includes/ /var/www/html/wp-includes/;
any ideas?
Thanks
Majal Mirasol · September 8, 2020 at 11:50 am
Hi Gregory! Thanks for stopping by. PageSpeed acts on the produced HTML before it is sent to Cloudflare. Does your site work if you disabled PageSpeed? If it does, then there your Cloudflare and SSL configurations are okay, and we can focus on PageSpeed configs. If it does not work, they you’ll have to fix those first.
PageSpeed configs are a bit tricky. You’ll have to experiment on what doesn’t break your site. At a quick glance though, I noticed that you used
domain.com
in your confs? I mean you should change it to your actual domain name if you have not done so yet.Bùi Lê Chí Bảo · June 19, 2021 at 12:37 am
Thank you! It worked on Centos 7 and Nginx 1.20.1!
Majal Mirasol · June 19, 2021 at 6:53 am
Thank you for letting us know! 🙂
Josh J. · March 15, 2022 at 3:51 am
What is wrong?
bash: ./mkpagespeed: /usr/bin/bash^M: bad interpreter: No such file or directory
Majal Mirasol · April 3, 2022 at 7:51 pm
I make my files in Linux, but your file must have been edited in Windows. Please see: https://unix.stackexchange.com/questions/32001/what-is-m-and-how-do-i-get-rid-of-it