Random header image

Compiling the HTTP Substitutions Filter module for NGINX on CentOS 7

I use NGINX for various things, including one niche case, where I rewrite and replace strings before presenting them to the user. I do this using the HTTP substitutions filter module. The readily-compiled module to accomplish this is included with the paid NGINX Plus, but is also available to DIY compile if you have the ability.

If you're just looking for precompiled .so files you can use with NGINX on CentOS 7 available from the nginx.org repository, see the end of this post.

A while ago I took the time to work out how to compile this for updates; the CentOS box I run NGINX on uses yum packages for updates, but then the subs filter module stops working. So, after half an hour or so of tinkering, quiet swearing, obtaining of additional packages, tweaking commandlines etc... I have a working oneliner to make an NGINX build which will also compile a suitable ngx_http_subs_filter_module.so file. 

To compile this dynamic module you generally need to build with the same switches used for the packaged build. So, first step was to find out how it was compiled:

nginx -V

nginx version: nginx/1.21.5
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

OK, good stuff. Until we add this dynamic module, if we try to start NGINX it won't load, complaining about the missing module (obviously), so next thing to do is obtain the community edition tarball and the module.

NGINX can be obtained from http://nginx.org/en/download.html; the latest version today (13 January 2022) is 1.21.5. Extract the tarball to a suitable location, ideally on the CentOS box you're planning to use.

Weibin Yao(姚伟斌) helpfully maintains a git repo for the HTTP Substitutions Filter dynamic module (and a few other useful modules). Grab a zipped clone of the repo from https://github.com/yaoweibin/ngx_http_substitutions_filter_module (click green Code -> copy the Download ZIP link and download that to your server). Extract the git master.zip to the same root folder as your freshly extracted NGINX tarball in a ngx_http_substitutions_filter_module subfolder.

cd to the nginx-1.21.5 folder. The salient info from nginx -V can then be incorporated into a new make build command:

/nginx/nginx-1.21.5# ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie' --add-dynamic-module=ngx_http_substitutions_filter_module

Once done (and you'll probably have various errors you'll need to resolve by installing various packages, as I did) go into the newly created objs subfolder. There you'll see a few freshly-compiled files including ngx_http_subs_filter_module.so which you must copy to the /usr/lib64/nginx/modules folder.

I tend to keep the old versions and rename the .so file with its compiled version on the end, then make a symlink with NGINX's expected module name to the current-version file in the same folder: ln -s ngx_http_subs_filter_module-1.21.5.so ngx_http_subs_filter_module.so

And with that, you're pretty much finished. Start up NGINX and it should work.


For convenience, here's the latest few versions of the module, for those who haven't the time or ability to compile themselves:

NB: these will almost certainly only work on CentOS 7, and the compiled flags (options) must match those of the version of nginx installed, including for all dynamic modules. If you previously compiled yourself, or obtained a precompiled build from a different yum repository (I use nginx's own yum repository) then your mileage will significantly vary. You can use repoquery on the commandline to find out which repository your system used. Other guides to use NGINX's own repo to install it on CentOS are available online. Some guides recommend the EPEL repo but I prefer to go direct to NGINX's own repo for this.

Any questions or suggestion for improvements, or spotted a mistake? Please drop me a comment!

Leave a Reply

Your email address will not be published.

Notify me of followup comments via email. You can also subscribe without commenting.

I