Coding Sun 17 January 2021, 15:14

Purge Nginx proxy cache without Nginx Plus

Nginx (engine x) can be used as a proxy with a caching function. So it can cache complete pages and make our applications a lot faster if we do it right. The hardest part about cache is controlling it, when is the content we saved still ok and when do we need to replace it with a new version. How do we purge the stale nginx proxy cache?

This is solved by the extended functionality of Nginx Plus and gives you the ability to bypass (update) or purge specific caches. The biggest issue is that Nginx Plus is quite expensive (around $2500 a year for a single license), while we can get the same functionality with a free module.

In this post I want to go over how to use the FRiCKLE ngx_cache_purge module to purge the proxy cache Nginx can create on Ubuntu.

No machine to test this on? Try DigitalOcean

Get $100 to test at DigitalOcean for 60 days and if you decide to continue and spend $25 I’ll receive $25.

FRiCKLE ngx_cache_purge module

The module has been developed by FRiCKLE Labs back in 2009 and is described as:

Module adding ability to purge content from nginx’s FastCGI, proxy, SCGI and uWSGI caches.

FRiCKLE Labs

Now it’s being maintained at the Community Nginx Modules on Github and the latest version can be found on the ngx_cache_purge releases page.

Nginx version and getting source to build a compatible module

At the time of writing the current latest LTS (Long Term Support) version of Ubuntu is 20.04 Focal Fossa. Firstly, we’ll install Nginx, we’ll use APT (Advanced Packaging Tool) as a package manager to pull the latest stable version from the repositories.

sudo apt-get update
sudo apt-get install nginx

Now that we’ve got Nginx installed let’s install the basics for building packages from source and get the source files for the current installed version of Nginx. Finally, we’ll need to get the latest version of ngx_cache_purge module. So we can build a dynamic module which is compatible with the version of Nginx we got installed.

sudo apt-get install build-essential lsb-release dpkg-dev libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev

Add the Nginx stable repository.

sudo add-apt-repository ppa:nginx/stable

Uncomment the deb-src line, so we can source the Nginx files for custom builds.

sed -i "s/^# //" /etc/apt/sources.list.d/nginx-ubuntu-stable-`lsb_release -sc`.list && apt-get update

After that go to the build directory and source Nginx.

cd /usr/local/src && apt-get source nginx

Finally we can download the ngx_cache_purge module files and start our build. You can find the latest release here, at the moment of writing it’s 2.5.1.

wget -q https://github.com/nginx-modules/ngx_cache_purge/archive/2.5.1.tar.gz && tar -xf 2.5.1.tar.gz

Build the ngx_cache_purge module

Now that we prepared everything build the module is 1 command away. With this command we go to the nginx-1.18.0 source folder (or change to the version you have). Then we configure the build to make our ngx_cache_purge module into a dynamic nginx module and make sure it’s compatible (–with-compat). And finally we tell it to build our modules.

cd /usr/local/src/nginx-1.18.0 && ./configure --add-dynamic-module=/usr/local/src/ngx_cache_purge-2.5.1 --with-compat && make modules

We should have a dynamic module now in the objs folder which we should copy to the modules folder of our Nginx install.

cp /usr/local/src/nginx-1.18.0/objs/ngx_http_cache_purge_module.so /usr/lib/nginx/modules/

Configuration

Now that we’ve build the module and added it to the Nginx modules folder we can add it into our configuration. Keep in mind that when we upgrade Nginx, we also need to rebuild the module and update it so it’s compatible with the new version. We can load the ngx_http_cache_purge_module.so in the nginx.conf file so we can use it in all server configurations. It should look something like the example below.

sudo nano /etc/nginx/nginx.conf
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;

# Cache purge module
load_module /etc/nginx/modules/ngx_http_cache_purge_module.so;

events {
    multi_accept       on;
    worker_connections 65535;
}

http {
    ...
}

To give a good insight into how we want this to help our page load times, below you can see the setup. With every request the Nginx proxy will check if it has a cached version of the requested page. If not it will forward the request to the application, which handles the request and sends it back to the proxy. The proxy will now cache the outcome of the request and the next time it will serve the cache.

Nginx Application Cache Proxy Purge example

To achieve this we will use the module with the request we want to be able to cache. We edit our server config and make sure we define the cache path and cache validity at the top of the file. After this we will define the cache settings for our test-page.

# Cache settings
proxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app_cache:10m max_size=2g inactive=120m use_temp_path=off;
proxy_cache_valid 200 60m;

# The server behind the proxy
upstream app {
    server 10.0.0.1;
}

# App proxy server
server {
    listen      443 ssl http2;
    listen      [::]:443 ssl http2;
    server_name app.com;

    ...

    # Cache settings for location
    location ^~ /test-page {
         proxy_buffering      on;
         proxy_cache          app_cache;
         proxy_cache_key      $uri$is_args$args;

         # From which IP do we allow purge requests
         # in the example the IP from the CMS
         proxy_cache_purge    PURGE from 111.111.111.111;

         proxy_ignore_headers Expires;
         proxy_ignore_headers Cache-Control;
         proxy_ignore_headers Set-Cookie;

         proxy_hide_header    Expires;
         proxy_hide_header    Cache-Control;
         proxy_hide_header    Set-Cookie;

         add_header X-Cached  $upstream_cache_status;
         proxy_pass           http://app;
    }
}

Add comment

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