Pagespeed: Microcaching with Nginx

Nginx is a very fast web server in itself - but it still offers some interesting caching features, minimizing access to PHP and delivering pages much faster. A short manual.

For this blog I use the current Nginx mainline version 1.7.0 with ngx_pagespeed modules as basis. For this I had to compile nginx by myself, but this is not a fundamental problem and with the appropriate instructions it is quickly done even on a current Debian system.
Here are my configure settings:

--prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_modules --with-http_realip_modules --with-http_addition_modules --with-http_sub_modules --with-http_dav_modules ---with-http_flv_modules --with-http_mp4_modules --with-http_gunzip_modules --with-http_gzip_static_modules --with-http_random_index_modules --with-http_secure_link_modules --with-http_stub_status_modules --with-http_auth_request_modules --with-mail --with-mail_ssl_modules --with-file-aio --with-http_spdy_modules --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,--as-needed' --with-ipv6 --add-module=../ngx_pagespeed-1.7.30.4-beta --add-module=../ngx_cache_purge-2.1

This allows nginx 1.7.0 to be used as a drop-in replacement for the nginx from the Debian repositories, all configuration directories remain the same. If there is something wrong with the self compiled version, you can also simply switch back to the original version.

Preparation for Microcaching

To use nginx microcaching the configuration must be adjusted. To do this in the folder /etc/nginx/conf.d create a new file, I have named it microcache.conf This will be automatically loaded into the main configuration file. The content of this file:

fastcgi_cache_path /dev/shm/microcache levels=1:2 keys_zone=microcache:5M max_size=1G inactive=2h;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache Control Expires Set-Cookie;

This creates a cache area of one gigabyte in a ramdisk called "microcache". If you can't or don't want to keep the cache in RAM, you can of course create a directory on the hard disk and use it. The key for each cache entry results from the protocol, the request method (POST or GET), the host and the called URL. This allows you to cache several WordPress blogs without overlapping.

Setup of caching for VirtalHosts

Most will work with a VirtualHost configuration. To cache the output of PHP, fastcgi must be configured accordingly. The following information must be added to the configuration file:

set $skip_cache 0;

# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
 set $skip_cache 1;
}

if ($query_string != "") {
 set $skip_cache 1;
}

# Don't cache uris containing the following segments
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml {
set $skip_cache 1;
    }

# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
set $skip_cache 1;
}

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

# process any php scripts, not found gets redirected through routestring
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_cache microcache;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Set cache key to include identifying components
fastcgi_cache_valid 200 1d;
fastcgi_cache_valid 302 301 1m;
fastcgi_cache_valid 404 1s;
fastcgi_cache_min_uses 1;
fastcgi_cache_use_stale error timeout invalid_header updating http_500;
fastcgi_ignore_headers Cache Control Expires;
fastcgi_pass_header Set-Cookie;
fastcgi_pass_header set cookie;
}

Conclusion

Compared to the solution I have used so far (Caching of whole pages via Memcached) the variant offers some advantages over the caching functions integrated in Nginx:

  • No access at all to PHP-FPM for cache-deliver
  • Pages can also be delivered if PHP returns an error (this is indicated by the line fastcgi_cache_use_stale reached)
  • For WordPress there are suitable plugins that make it easier to empty the cache (purge cache)

I will continue to use this setup here in the blog and see what other effects it has - fast loading times are already a fundamental advantage.

Leave a Reply

Your email address will not be published. Required fields are marked *