Skip to main content
Docs menu

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:

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.

  1. Add the repository.

    curl -fsSL https://packages.modpagespeed.com/install.sh | sudo sh
  2. Install the optimizer worker, before the module.

    sudo apt-get install pagespeed-optimizer   # Debian/Ubuntu
    sudo dnf install pagespeed-optimizer       # AlmaLinux/RHEL/Rocky

    The package creates the pagespeed user and group, and enables and starts pagespeed-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 pagespeed group 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-data on Debian and Ubuntu, sudo usermod -a -G pagespeed nginx on Enterprise Linux.

  3. Install the module.

    sudo apt-get install nginx-module-pagespeed   # Debian/Ubuntu
    sudo dnf install nginx-module-pagespeed       # AlmaLinux/RHEL/Rocky

    The package loads the module itself (through /etc/nginx/modules-enabled/ on Debian and Ubuntu, /usr/share/nginx/modules/ on Enterprise Linux), so add no load_module line.

  4. Set the shared settings. Create /etc/nginx/conf.d/pagespeed.conf; the stock nginx.conf of every supported distribution includes conf.d/*.conf inside its http block:

    # 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;

    GlobalAdminPath can only be set in the http block, and a FileCachePath there covers every server block. Leave out pagespeed standby; and the module is on in every server block, including the default server.

  5. 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; before deny all; for your operations network). Enterprise Linux has no snippets directory, 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; }
    EOF

    From the next release, the nginx-module-pagespeed package installs the same four location lines as /etc/nginx/snippets/pagespeed_admin_localhost.conf. Until then, create the file above by hand, under this name: the package leaves a hand-made pagespeed_admin_restrict.conf alone, 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 duplicate location blocks.

    Then, in each server block 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.conf includes /etc/nginx/default.d/*.conf; to turn the module on there, put pagespeed on;, the DaemonSocketPath and DaemonVolumePath lines and the include line in a file in that directory. That stock server has no default_server, and conf.d/*.conf is included before it, so a server you add in conf.d that listens on the same port becomes the default server.

  6. Restart nginx.

    sudo nginx -t && sudo systemctl enable nginx && sudo systemctl restart nginx

    enable matters on Enterprise Linux, where the nginx that dnf pulled in does not start at boot otherwise. Restarting also applies the nginx user’s new pagespeed group membership.

  7. 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 second 200. The same admin URL requested from another machine answers 403. To open the console from your workstation, tunnel to the server (ssh -L 8080:127.0.0.1:80 <you>@<server>), point <your-domain> at 127.0.0.1 in the workstation’s hosts file for the session, and browse to http://<your-domain>:8080/pagespeed_global_admin/: the request reaches nginx from 127.0.0.1 and 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 to https://<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.

Shapenginx versionWhere it comes from
Native module (nginx-module-pagespeed) on Debian 12 bookworm1.22.1the distribution’s stock nginx (amd64 + arm64)
Native module on Debian 13 trixie1.26.3the distribution’s stock nginx (amd64 + arm64)
Native module on Ubuntu 22.04 jammy1.18.0the distribution’s stock nginx (amd64 + arm64)
Native module on Ubuntu 24.04 noble1.24.0the distribution’s stock nginx (amd64 + arm64)
Native module on AlmaLinux / RHEL / Rocky 91.20.1the distribution’s stock nginx (x86_64 + aarch64)
Native module on AlmaLinux / RHEL / Rocky 10the distribution’s stock nginxthe distribution’s stock nginx (x86_64)
Docker / nginx reverse proxy (pagespeed-nginx and pagespeed-combined images)1.30.6bundled 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-optimizer package from the same repository, at the same release as nginx-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 pagespeed user. Its cache directory, notification socket and shared configuration are open to members of the pagespeed group only. When nginx-module-pagespeed is installed or upgraded and that group exists, the package adds the nginx user to it (www-data on Debian and Ubuntu, nginx on 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 example sudo 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.sock for the notification socket and /var/cache/pagespeed-optimizer/v3/cache for the cache volume. If you changed SOCKET_PATH or CACHE_DIR in /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;
}
  • FileCachePath works in either place: in the server block as above, or once in the http block 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 DaemonVolumePath on a different path from FileCachePath. 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 pagespeed group: 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 the pagespeed group (for example sudo 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

  1. 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.
  2. Request a stylesheet or script of your site a few times.
  3. Open the module’s statistics (the admin console’s Statistics page, or your StatisticsPath). ipro_daemon_served counts in-place requests answered from the optimizer’s cache, and ipro_daemon_fallthrough counts the ones passed to the ordinary path. Once the optimizer has built a variant, ipro_daemon_served rises. If only ipro_daemon_fallthrough rises, 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, a Vary on 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 with add_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 and ipro_daemon_served does not rise.
  • A request that nginx redirects internally (rewrite, a try_files fallback, 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.

Search