Build ngx_pagespeed from source
The maintained PageSpeed module for nginx is open source, and the full source tree is public at We-Amp/mod_pagespeed. It ships as a signed, prebuilt package for the common distributions, so most installs never compile anything. Build from source when you run a custom nginx, or a distribution without a signed package.
Recommended — install the maintained module from the signed repository. It's prebuilt and pinned to your distribution's nginx: no toolchain, and no rebuild every time you upgrade nginx.
curl -fsSL https://packages.modpagespeed.com/install.sh | sudo sh sudo apt install nginx-module-pagespeed # Debian / Ubuntu sudo dnf install nginx-module-pagespeed # AlmaLinux / RHEL 9 and 10
When to build from source
nginx loads a dynamic module only if it was built against the exact
nginx version and configuration it loads into — --with-compat
does not relax that. The signed packages are therefore built against
each distribution's stock nginx. Build from source when:
You run a custom nginx — the nginx.org repository, a self-compiled binary, or a build with extra modules — so no published package matches it.
Your distribution has no signed package — the packages cover Debian, Ubuntu, and the EL9/EL10 family; Amazon Linux and other distributions take this path.
You want to read or change the code. The nginx
module lives in
pagespeed/nginx/
of the mod_pagespeed tree, next to the Apache, IIS and Envoy
integrations. Contributions go through that repository.
The build is one script. It compiles the module's optimization
library with Bazel and then links the nginx glue with nginx's own
./configure --add-dynamic-module=… --with-compat and
make modules, so the module's version stamp matches the
nginx it will load into. It runs inside a container of the
distribution you deploy to, because the module inherits the build
host's glibc floor: a module built on a newer distribution will not
load on an older one.
Step 01
Get the source tree
Clone the public repository and check out the latest release tag. You need Docker on the build machine; everything else is installed inside the build container.
git clone https://github.com/We-Amp/mod_pagespeed.git
cd mod_pagespeed
git checkout "$(git tag --list 'v*' --sort=-v:refname | head -1)" # latest release tag
Step 02
Vendor the build dependencies
The container build runs offline, so populate the vendor/
directory once: the Bazel repository cache plus the Cyclone Cache
source. The script needs Bazel (or bazelisk) and network access; the
repository's dev container has both.
docker compose up -d docker compose exec dev tools/vendor-deps.sh docker compose down
On a machine that already has bazelisk, run
tools/vendor-deps.sh directly instead.
Step 03
Match your nginx version
Check the version you run. For a distribution's stock nginx, the build script fetches the matching source itself — on Ubuntu and EL it uses the distribution's own patched source, because a distro security update can change nginx's internal structures without changing the version number.
nginx -v
For a custom nginx, pin the exact release tarball: download it from nginx.org, verify its signature, and note its checksum. The build script refuses an unverified tarball.
curl -fsSLO https://nginx.org/download/nginx-1.26.3.tar.gz # substitute your version
sha256sum nginx-1.26.3.tar.gz
Step 04
Build inside the target distribution's container
Start a container of the distribution you deploy to, with the source tree mounted, and run the build script for that target. It installs the toolchain, fetches and pre-configures the nginx source, and builds the module.
# Debian 12 shown; use the image of the distribution you deploy to docker run --rm -it -v "$PWD":/src -w /src debian:12 bash # Inside the container — stock nginx: install/nginx/build_module_in_container.sh bookworm # Inside the container — custom nginx version (checksum from step 3): NGINX_SRC_VERSION=1.26.3 NGINX_SRC_SHA256=<sha256 of the tarball> \ install/nginx/build_module_in_container.sh bookworm
Targets: bullseye, bookworm, trixie
(Debian 11, 12, 13); jammy, noble (Ubuntu
22.04, 24.04); el9, el10 (AlmaLinux, Rocky
Linux, RHEL). The script's header documents the remaining overrides,
including building against a vanilla nginx.org tarball on Ubuntu or
EL. The result is
bazel-bin/pagespeed/nginx/ngx_pagespeed_module.so,
built for the container's architecture — run the build on an arm64
host for an arm64 module.
Step 05
Install, load, and verify
Copy the module into the nginx modules directory and load it:
sudo cp bazel-bin/pagespeed/nginx/ngx_pagespeed_module.so /usr/lib/nginx/modules/ # Debian / Ubuntu sudo cp bazel-bin/pagespeed/nginx/ngx_pagespeed_module.so /usr/lib64/nginx/modules/ # EL # At the top of nginx.conf, before the events block: load_module modules/ngx_pagespeed_module.so;
Add a minimal pagespeed configuration (see the
configuration reference), then reload nginx
and confirm the X-Page-Speed header:
sudo nginx -t && sudo systemctl reload nginx curl -sI https://yoursite/ | grep -i x-page-speed
Rebuild the module whenever you upgrade nginx. If a distribution security update changes nginx's internals under a module built earlier, the module detects the mismatch on the first request and degrades to pass-through with one alert in the error log instead of misbehaving.
The legacy open-source module
Google's original ngx_pagespeed remains archived at
apache/incubator-pagespeed-ngx, together with its wiki on
building PSOL from source. It has had no security patches since 2020
and none of the current features. The maintained tree above is its
drop-in continuation — existing pagespeed directives
keep working — so build from it rather than from the archive.
Licensing
mod_pagespeed 2.1 is open source under the Apache License 2.0 and free to install and run, in development and in production — no key, no token, no registration. Building from source does not change that.