Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I need Nginx to serve a file relative from document root if it exists, then fallback to an upstream server if it doesn't. This can be accomplished with something like:

server {
    listen       80;
    server_name  localhost;

    location / {
        root /var/www/nginx/;
        try_files $uri @my_upstream;
    }

    location @my_upstream {
        internal;
        proxy_pass  http://127.0.0.1:8000;
    }
}

Fair enough. The problem is, my upstream is not serving the contents of URI directly, but instead, returning X-Accel-Redirect with a location relative to document root (it generates this file on-the-fly):

% curl -I http://127.0.0.1:8000/animals/kitten.jpg__100x100__crop.jpg
HTTP/1.0 200 OK
Date: Mon, 26 Nov 2012 20:58:25 GMT
Server: WSGIServer/0.1 Python/2.7.2
X-Accel-Redirect: animals/kitten.jpg__100x100__crop.jpg
Content-Type: text/html; charset=utf-8

Apparently, this should work. The problem though is that Nginx tries to serve this file from some internal default document root instead of using the one specified in the location block:

2012/11/26 18:44:55 [error] 824#0: *54 open() "/usr/local/Cellar/nginx/1.2.4/htmlanimals/kitten.jpg__100x100__crop.jpg" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /animals/kitten.jpg__100x100__crop.jpg HTTP/1.1", upstream: "http://127.0.0.1:8000/animals/kitten.jpg__100x100__crop.jpg", host: "127.0.0.1:80"

How do I force Nginx to serve the file relative to the right document root? According to XSendfile documentation the returned path should be relative, so my upstream is doing the right thing.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

You need to have your root directive under server, and not under location. This is one of the most common nginx configuration mistakes.

share|improve this answer
    
Thanks. I changed the root rule to the server block and it almost worked. I had to change my upstream to return an URI starting with a slash, apparently Nginx ignored the last slash in the root rule. –  hcalves Nov 26 '12 at 21:42

Your backend produces incorrect X-Accel-Redirect header: the path part of URI must start with / (see RFC 3986).

share|improve this answer
    
Yep, figured it out. –  hcalves Nov 28 '12 at 14:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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