Nginx reverse proxy server not serving cached homepage correctly

Wesley Cripe asked:

I’ve been configuring a new server for a web development client recently, and run into an interesting problem. The site is fairly high-traffic, but the CMS is fairly heavy and inefficient at generating pages in realtime. This slows page loads down fairly significantly when a page needs to be generated directly from the CMS. The CMS is unfortunately tied to Apache for a number of reasons, so serving pages from it through nginx isn’t a viable option. Additionally, the Apache .htaccess file for the CMS is necessarily somewhat complex and involved, so requests served from Apache are relatively slow.

Due to these factors, I’m configuring nginx as a reverse proxy server, and have written a plugin for the CMS that will render pages to static HTML, to be stored in a specific cache directory wherever it’s reasonable. My intent is to configure nginx to serve requests for a cached file directly, thus avoiding apache (and more importantly, avoiding the CMS) entirely.

So far this process has gone smoothly, and I have nginx successfully serving the cached files generated by the CMS (at a nice, responsive 25ms, compared to the CMS’s 500+ ms), and passing through to the CMS if a cache file does not exist, all with one exception: the homepage. For some reason, the homepage location blocks don’t seem to be activating at all.

Here’s the site config (anonymized):

# reverse proxy config for, serves all non-dynamic files
server {
        listen 80;
        root            /var/www/;

        add_header "X-Index-0" "block-0";

        location ^~ ^(index)?\.?(htm|html|php|asp|aspx)?$ {
                try_files /var/www/ @apache;
                add_header "X-Index-1" "block-1";

        location / {
                try_files /var/www/ @apache;
                add_header "X-Index-2" "block-2";

        location ~ ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|js|ttf|woff|svg|otf)$ {
                etag on;
                expires 30d;

        location ~ ^(.+\.html)$ {
                root /var/www/;
                add_header "X-Cache-Hit" $uri;
                try_files $1 @apache;
                expires 7d;

        location @apache {
                add_header              'X-Block-Apache' 'block';
                proxy_set_header        'Host' $host;
                proxy_set_header        'X-Forwarded-From' $proxy_add_x_forwarded_for;

The problem is, every request for the root of the site ( gets routed to the @apache block, despite the presence of the /var/www/ (verified by opening it in a text editor with the same user nginx runs as). I added the add_header lines to each location block in an attempt to understand the location blocks that are being activated and in what order. Unfortunately, the only header I’m getting in response to the request is ‘X-Block-Apache’ one, indicating to me that neither of the location blocks targeted at the root of the site (and any requests for index files) are activating.

This impression is reinforced by the fact that going to gives me an ‘X-Cache-Hit’ header, and is very obviously served from nginx (something like 15x the speed compared to the page being served from the CMS). However, shouldn’t the first location block trigger in this case? What can I do to get the index file serving appropriately from nginx if visiting does not seem to trigger the “location /” block?

Thanks for any assistance!

My answer:

Your try_files is trying to load the file you specified, /var/www/, which doesn’t exist.

Remember that you need to specify the path relative to the document root.

try_files /cache/index.html @apache;

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.