Tutorials

How to setup mod_pagespeed with Nginx, varnish and PHP-FPM

What is mod_pagespeed It is a module / plugin which helps speed up the performance of the site, by doing the following things :

  • Combines & Minifies CSS and JS
  • Optimizes the cache for the files
  • Uses URL fingerprinting
  • Minifies HTML

To setup pagespeed, you need to first log in to your server via SSH.

Step 1 : Enter the following command

sudo apt-get install php5-fpm php5-cli php5-mysql varnish unzip

Step 2 : We need to build Nginx from source with mod_pagespeed

sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev

To Download ngx_pagespeed

cd
NPS_VERSION=1.9.32.4
wget https://github.com/pagespeed/ngx_pagespeed/archive/release-${NPS_VERSION}-beta.zip
unzip release-${NPS_VERSION}-beta.zip
cd ngx_pagespeed-release-${NPS_VERSION}-beta/
wget https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}.tar.gz
tar -xzvf ${NPS_VERSION}.tar.gz 

Now we build nginx with pagespeed support

cd
NGINX_VERSION=1.8.0
wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-${NGINX_VERSION}/
./configure --add-module=$HOME/ngx_pagespeed-release-${NPS_VERSION}-beta --with-http_gzip_static_module --with-http_realip_module
make
sudo make install

Step 3 : Next we need to configure Varnish. Open the file /etc/varnish/default.vcl and replace it with the following

backend default {
  .host = "127.0.0.1";
  .port = "8080";
}

acl purge {
  "127.0.0.1";
  "localhost";
}

sub vcl_recv {
    if (req.request == "PURGE") {
      if (!client.ip ~ purge) {
        error 405 "Not allowed.";
      }
      ban("req.url ~ "+req.url+" && req.http.host == "+req.http.host);
      error 200 "OK";
    }

    # only using one backend
    set req.backend = default;

    # set standard proxied ip header for getting original remote address
    set req.http.X-Forwarded-For = client.ip;

    # logged in users must always pass
    if( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ){
        return (pass);
    }

    # don't cache search results
    if( req.url ~ "\?s=" ){
        return (pass);
    }

    # always pass through posted requests and those with basic auth
    if ( req.request == "POST" || req.http.Authorization ) {
         return (pass);
    }

    # else ok to fetch a cached page
    unset req.http.Cookie;
    return (lookup);
}



sub vcl_fetch {

    # remove some headers we never want to see
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;

    # only allow cookies to be set if we're in admin area - i.e. commenters stay logged out
    if( beresp.http.Set-Cookie && req.url !~ "^/wp-(login|admin)" ){
        unset beresp.http.Set-Cookie;
    }

    # don't cache response to posted requests or those with basic auth
    if ( req.request == "POST" || req.http.Authorization ) {
         return (hit_for_pass);
    }

    # only cache status ok
    if ( beresp.status != 200 ) {
        return (hit_for_pass);
    }

    # don't cache search results
    if( req.url ~ "\?s=" ){
        return (hit_for_pass);
    }

    # else ok to cache the response
    set beresp.ttl = 24h;
    return (deliver);
}



sub vcl_deliver {
    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    }
    else {
        set resp.http.X-Cache = "MISS";
    }
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}

sub vcl_hit {
  if (req.request == "PURGE") {
    purge;
    error 200 "OK";
  }
}

sub vcl_miss {
  if (req.request == "PURGE") {
    purge;
    error 404 "Not cached";
  }
}


sub vcl_hash {
    hash_data( req.url );
    if ( req.http.host ) {
        hash_data( regsub( req.http.host, "^([^\.]+\.)+([a-z]+)$", "\1\2" ) );
    } else {
        hash_data( server.ip );
    }
    # ensure separate cache for mobile clients (WPTouch workaround)
    if( req.http.User-Agent ~ "(iPod|iPhone|incognito|webmate|dream|CUPCAKE|WebOS|blackberry9\d\d\d)" ){
        hash_data("touch");
    }
    return (hash);
}

Step 4 : Setup nginx init script

 cd /etc/init.d
 wget https://raw.githubusercontent.com/JasonGiedymin/nginx-init-ubuntu/master/nginx
 chmod +x nginx
 update-rc.d nginx defaults

Step 5 : Assuming you have your WordPress sites installed under the /srv/www/ folder. Open the Nginx conf file, /usr/local/nginx/conf/nginx.conf and replace it with the following :

server {
        listen       8080;
        server_name  test.com;

        root /srv/test.com;
        index index.php index.html;

        location / {
                try_files $uri $uri/ /index.php?$args;
        }

        location ~ .php$ {
                try_files $uri /index.php;
                include fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_index index.php;
        }

        pagespeed On;
        pagespeed ModifyCachingHeaders on;

        # Needs to exist and be writable by nginx.
        pagespeed FileCachePath "/var/cache/ngx_pagespeed/";
        pagespeed LoadFromFile "https://yourdomain.com" "/srv/yourdomain.com";
        pagespeed MapOriginDomain "http://localhost" "https://yourdomain.com";
        pagespeed EnableFilters rewrite_css,combine_css,trim_urls;
                pagespeed DisableFilters sprite_images,convert_jpeg_to_webp,convert_to_webp_lossless;

}

Now restart Nginx and varnish

service nginx restart
service varnish restart

To verify if the setup was done properly, you can try the following command :

curl -i https://yourdomain.com

This should return 2 headers, i.e X-Page-Speed and X-Cache.


Copyright © 2018 WPOven