Install the module on Apache and nginx
Last updated Edit this page View as Markdown
Install the native mod_pagespeed 2.1 module for Apache and nginx from the signed package repository: distributions, nginx compatibility, worker pairing.
On this page
mod_pagespeed ships a native module for Apache and nginx. You have three working options:
- Native Apache module — install from the signed packages.modpagespeed.com repository, or the cPanel / EasyApache 4 guide on cPanel hosts.
- Native nginx module — install from the signed packages.modpagespeed.com repository.
- Docker / nginx reverse proxy — run the Docker / nginx reverse proxy in front of your origin.
Machine-readable recipes for coding agents: modpagespeed.com/recipes/nginx.md and modpagespeed.com/recipes/apache.md (see Install with a coding agent).
Native Apache module
The signed repository at packages.modpagespeed.com ships the Apache module
(mod-pagespeed) — the same channel mod_pagespeed 1.15 uses — for Apache
2.4+:
curl -fsSL https://packages.modpagespeed.com/install.sh | sudo sh
sudo apt-get install mod-pagespeed # Debian/Ubuntu
sudo dnf install mod-pagespeed # AlmaLinux/RHEL/Rocky
sudo systemctl restart apache2 # Debian/Ubuntu
sudo systemctl restart httpd # RHEL family
The module keeps the same directive surface and filter names, so an existing
mod_pagespeed configuration carries over unchanged — see the
configuration reference for the full directive
set. The package also drops a default pagespeed.conf (in
/etc/apache2/mods-available/ on Debian/Ubuntu, /etc/httpd/conf.d/ on
RHEL) — edit that file to turn filters on. The Apache packages also install the
configuration that points the module at the pagespeed-optimizer worker, so the
module reaches the worker without further configuration.
Running Apache under cPanel/WHM? Use the signed EasyApache 4 RPM instead — see the cPanel / EasyApache 4 guide. See Install from packages.modpagespeed.com for the full distribution matrix (including the yum packages) and the nginx module.
Native nginx module
The signed repository at packages.modpagespeed.com ships the native nginx
module (nginx-module-pagespeed) — the same channel mod_pagespeed 1.15 uses —
for Debian and Ubuntu on amd64 and arm64, and for AlmaLinux, RHEL and Rocky 9
and 10. It is the ngx_pagespeed port of mod_pagespeed, built from the
mod_pagespeed source, and it loads into the nginx your distribution ships.
Each build is pinned to that distribution’s stock nginx (1.18 through 1.26),
so there is no version to match by hand.
The steps below install the module the way the Apache packages install the
Apache module: with the pagespeed-optimizer worker beside it. With the worker
paired, the module records each eligible CSS, JavaScript and image response
into the worker’s cache, the worker builds the optimized variants off the
request path, and the module serves the variant that fits each client. The
module’s own filters also work without the worker: leave out step 2 and the
DaemonSocketPath and DaemonVolumePath lines in step 5 to run it alone.
-
Add the repository.
curl -fsSL https://packages.modpagespeed.com/install.sh | sudo sh -
Install the optimizer worker, before the module.
sudo apt-get install pagespeed-optimizer # Debian/Ubuntu sudo dnf install pagespeed-optimizer # AlmaLinux/RHEL/RockyThe package creates the
pagespeeduser and group, and enables and startspagespeed-optimizer.service. These steps are for a host that runs systemd; in a container, use the Docker images.Install the worker on its own, before the module, never both in one command: the module package adds the nginx user to the
pagespeedgroup only if that group already exists when its install script runs, and in a single transaction dnf runs the module’s script first. On a host where the module went in first or alongside, add the user yourself and restart nginx:sudo usermod -a -G pagespeed www-dataon Debian and Ubuntu,sudo usermod -a -G pagespeed nginxon Enterprise Linux. -
Install the module.
sudo apt-get install nginx-module-pagespeed # Debian/Ubuntu sudo dnf install nginx-module-pagespeed # AlmaLinux/RHEL/RockyThe package loads the module itself (through
/etc/nginx/modules-enabled/on Debian and Ubuntu,/usr/share/nginx/modules/on Enterprise Linux), so add noload_moduleline. -
Set the shared settings. Create
/etc/nginx/conf.d/pagespeed.conf; the stocknginx.confof every supported distribution includesconf.d/*.confinside itshttpblock:# Off in every server block that does not turn it on. pagespeed standby; pagespeed FileCachePath /var/cache/ngx_pagespeed; # The admin console; step 5 restricts it. pagespeed GlobalAdminPath /pagespeed_global_admin;GlobalAdminPathcan only be set in thehttpblock, and aFileCachePaththere covers every server block. Leave outpagespeed standby;and the module is on in every server block, including the default server. -
Turn it on for your site. Create the restriction for the admin pages,
/etc/nginx/snippets/pagespeed_admin_restrict.conf(localhost only; add, for example,allow 10.0.0.0/8;beforedeny all;for your operations network). Enterprise Linux has nosnippetsdirectory, so create it first:sudo mkdir -p /etc/nginx/snippets sudo tee /etc/nginx/snippets/pagespeed_admin_restrict.conf >/dev/null <<'EOF' # PageSpeed admin pages, localhost only. location = /pagespeed_admin { allow 127.0.0.1; allow ::1; deny all; } location ^~ /pagespeed_admin/ { allow 127.0.0.1; allow ::1; deny all; } location = /pagespeed_global_admin { allow 127.0.0.1; allow ::1; deny all; } location ^~ /pagespeed_global_admin/ { allow 127.0.0.1; allow ::1; deny all; } EOFFrom the next release, the
nginx-module-pagespeedpackage installs the same fourlocationlines as/etc/nginx/snippets/pagespeed_admin_localhost.conf. Until then, create the file above by hand, under this name: the package leaves a hand-madepagespeed_admin_restrict.confalone, but a hand-made file under the packaged name makes the package upgrade stop and ask on Debian and Ubuntu (on Enterprise Linux, rpm keeps the hand-made file and saves the packaged copy beside it as.rpmnew). Include one of the two files, not both: nginx rejects the duplicatelocationblocks.Then, in each
serverblock that should be optimized:server { listen 80; server_name <your-domain>; pagespeed on; # The optimizer worker: its notification socket and its cache volume. pagespeed DaemonSocketPath /run/pagespeed-optimizer/notify.sock; pagespeed DaemonVolumePath /var/cache/pagespeed-optimizer/v3/cache; # Every server block with `pagespeed on` serves the admin console. include /etc/nginx/snippets/pagespeed_admin_restrict.conf; }On Enterprise Linux the stock server in
/etc/nginx/nginx.confincludes/etc/nginx/default.d/*.conf; to turn the module on there, putpagespeed on;, theDaemonSocketPathandDaemonVolumePathlines and theincludeline in a file in that directory. That stock server has nodefault_server, andconf.d/*.confis included before it, so a server you add inconf.dthat listens on the same port becomes the default server. -
Restart nginx.
sudo nginx -t && sudo systemctl enable nginx && sudo systemctl restart nginxenablematters on Enterprise Linux, where the nginx thatdnfpulled in does not start at boot otherwise. Restarting also applies the nginx user’s newpagespeedgroup membership. -
Check it.
curl -s -o /dev/null -D - -H 'Host: <your-domain>' http://127.0.0.1/ | grep -i '^x-page-speed' curl -s -o /dev/null -w '%{http_code}\n' -H 'Host: <your-domain>' http://127.0.0.1/pagespeed_global_admin/Run them on the server. The first prints
X-Page-Speed: <version>, the second200. The same admin URL requested from another machine answers403. To open the console from your workstation, tunnel to the server (ssh -L 8080:127.0.0.1:80 <you>@<server>), point<your-domain>at127.0.0.1in the workstation’s hosts file for the session, and browse tohttp://<your-domain>:8080/pagespeed_global_admin/: the request reaches nginx from127.0.0.1and selects your server block by its name. For a site that redirects port 80 to HTTPS, tunnel port 443 instead (ssh -L 8443:127.0.0.1:443 <you>@<server>) and browse tohttps://<your-domain>:8443/pagespeed_global_admin/. Its Statistics page shows whether the worker is in use: see Check that it works.
The admin console guide covers the other handler
paths (AdminPath, StatisticsPath, …) and their restrictions, and
Using the optimizer worker with nginx
the details of the pairing: other paths, start order, upgrades, and what happens
when the worker is not available.
See Install from packages.modpagespeed.com for the full distribution matrix (including the yum packages) and the Apache module. The signed packages also sidestep the ngx_pagespeed build failures on modern nginx that come from compiling the old module from source.
nginx compatibility
Two shapes, two nginx stories. The native module runs inside the nginx your distribution ships and is built for exactly that version; the Docker reverse proxy brings its own nginx inside the image.
| Shape | nginx version | Where it comes from |
|---|---|---|
Native module (nginx-module-pagespeed) on Debian 12 bookworm | 1.22.1 | the distribution’s stock nginx (amd64 + arm64) |
| Native module on Debian 13 trixie | 1.26.3 | the distribution’s stock nginx (amd64 + arm64) |
| Native module on Ubuntu 22.04 jammy | 1.18.0 | the distribution’s stock nginx (amd64 + arm64) |
| Native module on Ubuntu 24.04 noble | 1.24.0 | the distribution’s stock nginx (amd64 + arm64) |
| Native module on AlmaLinux / RHEL / Rocky 9 | 1.20.1 | the distribution’s stock nginx (x86_64 + aarch64) |
| Native module on AlmaLinux / RHEL / Rocky 10 | the distribution’s stock nginx | the distribution’s stock nginx (x86_64) |
Docker / nginx reverse proxy (pagespeed-nginx and pagespeed-combined images) | 1.30.6 | bundled in the image |
nginx refuses to load a module built for a different version, and
--with-compat does not relax that check, so the native module follows your
distribution’s nginx package, not nginx.org’s. Running an nginx we do not
package? Contact us for a matching pinned build. Debian 11
(bullseye) stays on the repository’s final 1.15.0 module packages.
Using the optimizer worker with nginx
The native nginx module can hand in-place optimization to the optimizer
worker (the pagespeed-optimizer package), as the Apache module does. With two directives set in a server block, the
module records each eligible resource into the optimizer’s cache, the
optimizer builds optimized variants of it, and the module serves the variant
that fits each client from that cache. With both directives unset, in-place
optimization works exactly as before.
Before you start
- Install the optimizer of the same release. Install the
pagespeed-optimizerpackage from the same repository, at the same release asnginx-module-pagespeed, and start it. The module and the optimizer are a matched pair: install, upgrade and roll them back together. - Let nginx reach the optimizer’s files. The optimizer runs as the
unprivileged
pagespeeduser. Its cache directory, notification socket and shared configuration are open to members of thepagespeedgroup only. Whennginx-module-pagespeedis installed or upgraded and that group exists, the package adds the nginx user to it (www-dataon Debian and Ubuntu,nginxon the RHEL family). If you installed the module before the optimizer or in the same command, or nginx runs as another user, add the user yourself, for examplesudo usermod -a -G pagespeed www-data, then restart nginx; the restart also applies the new group membership. - Find the two paths. The packaged optimizer’s defaults are
/run/pagespeed-optimizer/notify.sockfor the notification socket and/var/cache/pagespeed-optimizer/v3/cachefor the cache volume. If you changedSOCKET_PATHorCACHE_DIRin/etc/default/pagespeed-optimizer, use those values instead: the volume path is the cache directory followed by/cache.
Configuration
Set both directives in each server block that should use the optimizer:
server {
listen 80;
server_name <your-domain>;
pagespeed on;
pagespeed FileCachePath /var/cache/ngx_pagespeed;
# The optimizer worker: its notification socket and its cache volume.
pagespeed DaemonSocketPath /run/pagespeed-optimizer/notify.sock;
pagespeed DaemonVolumePath /var/cache/pagespeed-optimizer/v3/cache;
}
FileCachePathworks in either place: in theserverblock as above, or once in thehttpblock as in step 4, which then covers every server block.- Set the two together. With only one of them set, in-place optimization is off and the error log says that both are needed.
- Keep
DaemonVolumePathon a different path fromFileCachePath. The module’s own cache and the optimizer’s cache are separate. - nginx connects to the optimizer when it starts. After you change either directive, restart nginx.
Start order and upgrades
The packaged optimizer service is ordered ahead of nginx.service and waits
up to 30 seconds for its notification socket before it counts as started, so
at boot nginx starts after the optimizer. The ordering does not make nginx depend on the
optimizer: nginx still starts when the optimizer is absent. An nginx that
runs under another unit name is not ordered against the optimizer; give it an
ordering drop-in (After=pagespeed-optimizer.service).
When you upgrade, upgrade and start the optimizer first, let it create its cache volume, then restart nginx. If nginx starts in between, in-place optimization is off until you restart nginx, with the reason in the error log. After an update that changes the cache format, a fresh start of nginx in that window can fail instead, again with the reason in the error log. Starting the optimizer and then restarting nginx clears both.
When the optimizer is not available
If the directives are set but the optimizer cannot be used — it is not running, it is a release this module cannot work with, or nginx is not allowed to reach its files — then for that server:
- in-place optimization is off, and nginx serves every request normally;
- nginx logs the reason. When nginx is not allowed to reach the optimizer’s
files, the log does not name the
pagespeedgroup: nginx repeats a warning that the optimizer’s cache volume “cannot be used yet” because the worker “does not publish the size of its cache volume”, once per attempt, and nothing is optimized; after about six minutes it stops retrying and logs one error. If the optimizer is running, add the nginx user to thepagespeedgroup (for examplesudo usermod -a -G pagespeed www-data) and restart nginx; - when nginx refuses the optimizer at startup, the same reason appears once in the admin console’s message history.
The module’s own in-place path does not take over in that case. Fix the cause and restart nginx.
Check that it works
- Run
sudo nginx -t, restart nginx, and read the nginx error log. A working pair logs no repeated warning about the optimizer; the one error line you may see is a note about left-over cache volume files after you change the optimizer’s cache size. - Request a stylesheet or script of your site a few times.
- Open the module’s statistics (the admin console’s Statistics page, or your
StatisticsPath).ipro_daemon_servedcounts in-place requests answered from the optimizer’s cache, andipro_daemon_fallthroughcounts the ones passed to the ordinary path. Once the optimizer has built a variant,ipro_daemon_servedrises. If onlyipro_daemon_fallthroughrises, see Limits.
The admin console’s optimizer worker panels
read the optimizer’s management API through the separate
DaemonApiSocketPath directive.
Limits
- A response that carries headers this path cannot reproduce from the cache —
a
Set-Cookie, a CORS or security header, aVaryon another axis — is served by the ordinary path: complete, but not optimized in place. This includes headers your own nginx configuration adds to every response withadd_header(an HSTS header, for example): the module cannot tell them apart from headers the origin sent. On a server that sets such a header site-wide, little or nothing is optimized in place andipro_daemon_serveddoes not rise. - A request that nginx redirects internally (
rewrite, atry_filesfallback,index,error_page) is not optimized in place. - By default the module serves the uncompressed optimized copy and nginx
compresses it as configured.
pagespeed DaemonServeStoredEncodings on;sends the optimizer’s stored gzip and brotli copies instead; it is off by default.
Docker / nginx reverse proxy
The Docker / nginx reverse proxy runs the same
optimization core in front of any HTTP origin. It uses the thin nginx module,
bundled in its own nginx inside the pagespeed-nginx and pagespeed-combined
images and paired with the optimizer worker. The thin module’s file is also
named ngx_pagespeed_module.so, but it is a different module from the native
one above (see Two nginx modules, one file name). The
pair provides
image transcoding,
CSS/JS minification, critical CSS, and zero-copy serving from the Cyclone
shared-memory cache.
Run your site through a PageSpeed Insights test to see which failing audits mod_pagespeed will fix, and read the Core Web Vitals guide for the LCP, CLS, and INP plan.
Frequently asked questions
Is there a native nginx module for mod_pagespeed 2.1?
Yes. The native Apache and nginx module ships from the signed packages.modpagespeed.com repository — the same channel mod_pagespeed 1.15 uses.
How do I run mod_pagespeed on nginx today?
Two options. Install the native nginx module — a dynamic module from the signed packages.modpagespeed.com repository, built for Debian and Ubuntu on amd64 and arm64 and pinned to each distribution stock nginx (1.18 to 1.26). Or put the Docker / nginx reverse proxy in front of your origin. Install the optimizer worker (pagespeed-optimizer) first, then the module, and set pagespeed DaemonSocketPath and pagespeed DaemonVolumePath in the server block so the module hands in-place optimization to the worker; the module also runs without the worker, on its own filters only.