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

I am running into an odd problem for which I am not sure if it is a configuration issue or a bug in nginx. My setup is a nginx reverse proxy which has Apache2 backend servers. The load balancer is pretty basic similar to the example from the wiki, e.g. simplified:

http {
  upstream myproject {
    server 127.0.0.1:8000;
  }

  server {
    listen 80;
    location / {
      proxy_pass http://myproject;
    }
  }
}

Now, a problem arises for example when I try to request a directory in Apache, without the trailing slash at the end of the url. For example, a client requests:

http://apache.myserver.com/somedirectory

Apache will reply with a HTTP 302 to redirect the client to

http://apache.myserver.com/somedirectory/

Note the url has a slash in the end to note that it is a directory. Also note that Apache is "smart" by using the incoming request hostname in the redirect header. All fine so far. However, when using nginx with load balancing, this 301 is sent to the client without translating the nginx upstream name back to an actual server/domain. So the client will receive the following:

GET http://nginx.myserver.com/somedirectory
HTTP 301 Moved Permanently
...
Location: http://myproject:8000/somedirectory/

The myproject is the name of the nginx upstream backend. It is not an actual host that the client can resolve. It seems to me that instead the client should have been redirected to

http://nginx.myserver.com/somedirectory/  

I.e. the name of the upstream backend should have been replaced in the response header. Is this a bug in nginx or am I doing something wrong?

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Turns out nginx has quite a lot of proxy redirect options to deal with this sort of problems. I ended up using something like this:

location / {
    proxy_pass  http://myproject;
    proxy_set_header Host myproject;
    proxy_redirect http://myproject/ $scheme://$host/;
    proxy_redirect http://myproject:8000/ $scheme://$host/;
}

This basically replaces the upstream name with the $host and removes the port. This worked in my case because I am hosting nginx on the default ports for HTTP/HTTPS. If nginx is running on a non-default port, something like this is needed:

    proxy_redirect http://myproject/ $scheme://$host:$server_port/;
    proxy_redirect http://myproject:8000/ $scheme://$host:$server_port/;
share|improve this answer

Try using server_name_in_redirect like this:

server_name_in_redirect off;

If that doesn't work you might need to do something with proxy_redirect, although it sounds like your backend is behaving correctly.

share|improve this answer

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.