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 example.com, serves all non-dynamic files
server {
        listen 80;
        server_name     example.com www.example.com;
        root            /var/www/example.com/;

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

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

        location / {
                try_files /var/www/example.com/cache/index.html @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/example.com/static-cache;
                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 (example.com) gets routed to the @apache block, despite the presence of the /var/www/example.com/cache/index.html (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 http://example.com/index.html 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 example.com does not seem to trigger the "location /" block?

Thanks for any assistance!


Your try_files is trying to load the file you specified, /var/www/example.com/var/www/example.com/cache/index.html, which doesn't exist.

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

try_files /cache/index.html @apache;
  • That did indeed fix it--thank you very much! All of that debugging, and it turns out the correct answer is "I'm an idiot". I am still slightly curious as to why the add_header lines in the other blocks were not actually adding headers even if the try_files directives could not find the first file, but that's an academic question at this point, as they're now unnecessary – Wesley Cripe Mar 5 '14 at 19:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.