Recently I have enabled NGINX FactCGI caching in our Digital Ocean Droplet in order to reduce the Time To First Byte (TTFB) of this blog. However, one drawback of this caching is there is no support provided by the Nginx Open Source webserver to purge the cache when a page is modified. There is a separate ngx_cache_purge module available which has to be compiled with Nginx code to enable cache purging.
Disclosure: Please note that some of the links in the post are referral links. Read more about the policy here.
There are 3 solutions to add this module to Nginx:
- Compile NGINX & Cache Purge Module. It will pollute the production system with compilation software. Also, we need to recompile with every new Nginx version.
- Go for Nginx plus paid version
- Compile NGINX with NGX_CACHE_PURGE module in a development server and copy the compiled module to the NGINX in the production server and load it. Also, we need to recompile with every new Nginx version.
Obviously, I went with the 3rd solution since I don’t want our blog to be down and I don’t wanna pollute the production system. Let’s see how we can compile the NGX_CACHE_PURGE module and load it to the running Nginx in the production server.
Step 1: Get Nginx Configure Arguments
Run the following command in the production server:
nginx -V
Output
nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.1 11 Sep 2018
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-H4cN7P/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module
Make note of the currect version and copy all the configure arguments which starts with --with-
and keep it for use later
Step 2: Get Nginx Source Code
Get the Nginx source code of the version that is installed in your production server. I would recommend to do these operations in a non-prod server. So that we don’t end up polluting the production server with unnessary softwares.
I’ve created a new Digital Ocean Droplet just for this compilation. Now let’s login to the dev server and navigate to the /tmp/
directory and execute the following command.
wget http://nginx.org/download/nginx-1.14.0.tar.gz
Step 3: Get Nginx Cache Purge Code
At the time of this writing, 2.3 is the latest version. You can check the latest version here.
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
Step 4: Extract the files
for filename in *.tar.gz; do tar zxf $filename; done
Step 5: Replace Config File
Get this config file which was updated with the ability to compile the module as dynamic.
wget https://raw.githubusercontent.com/nginx-modules/ngx_cache_purge/master/config
Now replace the ngx_cache_purge-2.3/config
file with the above one.
cp config ngx_cache_purge-2.3/config
Step 6: Install Build Essentials and Libraries
apt-get update && apt-get install build-essential
HTTP rewrite module requires the PCRE library.
apt-get install libpcre3-dev
SSL modules require the OpenSSL library
apt-get install libssl-dev
HTTP gzip module requires the zlib library
apt-get install zlib1g-dev
HTTP XSLT module requires the libxml2/libxslt
libraries.
apt-get install libxml2-dev libxslt1-dev
HTTP image filter module requires the GD library
apt-get install libgd-dev
GeoIP module requires the GeoIP library
apt-get install libgeoip-dev
Step 7: Add Nginx Cache Purge Dynamic Module
Navigate to the nginx-1.14.0
directory
cd nginx-1.14.0
Execute the following command with the configure arguments
that we copied in Step 1. If you don’t include all the configure arguments, then the compiled module will not be compatible with the Nginx running in the production server.
./configure --add-dynamic-module=../ngx_cache_purge-2.3
So the final command would be something like this:
./configure --add-dynamic-module=../ngx_cache_purge-2.3 --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-H4cN7P/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module
Note: You may get errors due to missing dependencies required for compilation. Just install the required libraries if it complains.
If it executes successfuly, then the output would be something similar to this:
configuring additional dynamic modules
adding module in ../ngx_cache_purge-2.3
+ ngx_http_cache_purge_module was configured
checking for PCRE library ... found
checking for PCRE JIT support ... found
checking for OpenSSL library ... found
checking for zlib library ... found
checking for libxslt ... found
checking for libexslt ... found
checking for GD library ... found
checking for GD WebP support ... found
checking for GeoIP library ... found
checking for GeoIP IPv6 support ... found
creating objs/Makefile
Configuration summary
+ using threads
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/usr/share/nginx"
nginx binary file: "/usr/share/nginx/sbin/nginx"
nginx modules path: "/usr/lib/nginx/modules"
nginx configuration prefix: "/etc/nginx"
nginx configuration file: "/etc/nginx/nginx.conf"
nginx pid file: "/run/nginx.pid"
nginx error log file: "/var/log/nginx/error.log"
nginx http access log file: "/var/log/nginx/access.log"
nginx http client request body temporary files: "/var/lib/nginx/body"
nginx http proxy temporary files: "/var/lib/nginx/proxy"
nginx http fastcgi temporary files: "/var/lib/nginx/fastcgi"
nginx http uwsgi temporary files: "/var/lib/nginx/uwsgi"
nginx http scgi temporary files: "/var/lib/nginx/scgi"
Step 8: Make Modules
make modules
This command will throw some casting errors. Just ignore them. At this point, the cache purge module would have already compiled as ngx_http_cache_purge_module.so
in the objs
directory.
Step 9: Enable Nginx Cache Purge Module
Now you can copy ngx_http_cache_purge_module.so
file to Nginx’s modules directory in the production server. To enable this module, add the following to /etc/nginx/nginx.conf
and reload Nginx:
load_module modules/ngx_http_cache_purge_module.so;
For me I had to configure differently. First I had copied this file to the modules directory from the tmp
folder in the live server.
sudo cp ngx_http_cache_purge_module.so /usr/lib/nginx/modules/
Then, created a new file mod-http-cache-purge.conf
in the /usr/share/nginx/modules-available
directory with the load_module
directive:
load_module modules/ngx_http_cache_purge_module.so;
Then, created a symlink with the following command
ln -s /usr/share/nginx/modules-available/mod-http-cache-purge.conf /etc/nginx/modules-enabled
Then, reloaded Nginx. Whenever you change your NGINX config, run sudo nginx -t
before you do “sudo service nginx reload
” just to make sure you don’t break stuff.
sudo service nginx reload
References
https://github.com/FRiCKLE/ngx_cache_purge/issues/63
Conclusion
That’s all folks. In this article, we have added Cache Purging support to our existing Nginx web server without any down time in the live server.