Nginx with PCRE

How to enable Perl compatible regular expressions in Nginx

A CGI use case

Imagine you’re working on a legacy website that’s being converted to purely static HTML pages. The project was originally built using CGI scripts (oh, the good old days) and now your boss wants all the old URLs ending in .cgi to redirect to their equivalent .html counterparts. Because your team has decided to use Nginx to serve the new website, you come up with the following nginx.conf file:

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include mime.types;
    default_type application/octet-stream;

    sendfile on;
    keepalive_timeout 65;

    server {
        listen 80;

        location / {
            root html;
            index index.html index.htm;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }

        location ~ \.cgi$ {
            rewrite ^(.*)\.cgi$ $1.html last;
            return 301;
        }
    }
}

Forget the stuff at the top and focus on the highlighted chunk—the location block. Those four lines are all you need in order to fulfil the redirection requirement. If you use this configuration file on a vanilla Nginx, though, that location rule won’t be honored. You can confirm that by spinning up a new Nginx Docker container based on the default official image (I’m assuming the config file above was placed in your current directory):

docker run -d \
--name nginx \
-v $PWD/nginx.conf:/usr/local/nginx/conf/nginx.conf:ro \
-p 8080:80 \
nginx

If you try to open index.cgi in your browser, you’ll get a 404 Not Found response from Nginx. That’s because PCRE is required for regular expressions’ support in the location directive and for ngx_http_rewrite_module to kick in, but Nginx doesn’t come integrated with it out of the box.

Compiling Nginx with PCRE

The solution is to compile Nginx with support for the PCRE library:

FROM centos:7

RUN yum group install -y "Development Tools"
RUN yum install -y \
    zlib-devel \
    pcre-devel

ENV NGINX_VERSION 1.15.3
WORKDIR /tmp
RUN curl https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz | tar -xzv
WORKDIR /tmp/nginx-$NGINX_VERSION
RUN ./configure --with-pcre --with-pcre-jit
RUN make && make install

WORKDIR /
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]

To build an image out of this Dockerfile, use the following:

docker build --tag nginx-pcre .

And, to run it using your current directory and port 8081 on your host:

docker run -d \
--name nginx-pcre \
-v $PWD/nginx.conf:/usr/local/nginx/conf/nginx.conf:ro \
-p 8081:80 \
nginx-pcre

index.cgi should now permanently redirect you to index.html.

I don’t know how long you’ve been using the Internet for, but all this CGI talk made me feel nostalgic, so I’ll prove that the PCRE redirection rule worked by opening the page on Mosaic :)

/img/2018/09/2018-09-18-nginx-with-pcre/nginx-pcre-thumb.jpg

Nginx welcome page as shown by Mosaic!

Conclusion

By compiling Nginx with the PCRE library, you can perform complex manipulations with your location blocks and use the powerful rewrite and return directives. For information on what else can be done with PCRE and rewrite rules, check the Nginx blog.

docker  nginx  regex  web