Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In Nginx we have been trying to redirect a URL as follows: ->

where the user still sees the original URL in their browser. Once the user is redirected, say they click on the link to /section/index.html, we would want this to make a request that leads to the redirect ->

and again still preserve the original URL.

Our attempts have involved various solutions using proxies and rewrite rules, and below shows the configuration that has brought us closest to a solution (note that this is the web server configuration for the web server). However, there are still two problems with this:

  • It does not perform the rewrite properly, in that the request URL received by the web server includes /some/path and therefore fails to serve the required page.
  • When you hover on a link once a page has been served, /some/path is missing from the URL

    server {
        listen          80;
        location /some/path/ {
            proxy_set_header Host $host;
        location / {
            index index.html;
            root  /var/www/;

We are looking for a solution that only involves changing the web server configuration on We are able to change the config on (also Nginx), however we want to try and avoid this because we will need to repeat this setup for hundreds of different servers whose access is proxied through

share|improve this question
up vote 26 down vote accepted

First, you shouldn't use rootdirective inside the location block, it is a bad practice. In this case it doesn't matter though.

Try adding a second location block:

location ~ /some/path/(?<section>.*)/index.html {
    proxy_set_header Host $host;

This captures the part after /some/path/ and before index.html to a $section variable, which is then used to set the proxy_pass destination. You can make the regex more specific if you require.

share|improve this answer
Apologies for the late reply - this is so close to achieving what we are looking for. The only shortcoming is that, once the target page has been served, the URLs for links in the browser don't include '/some/path/' in them, meaning that they don't work if a user clicks on them. If we can work out how to overcome this I will update and accept this answer, as it's so nearly there. – robjohncox Apr 24 '14 at 9:32
The links the browser see are generated by the software that is running on server. You should modify that software in order to achieve what you want. – Tero Kilkanen Apr 27 '14 at 18:18
Thanks Tero - that sorts out what I was looking to do – robjohncox May 6 '14 at 13:21
not sure I follow your warning about root inside location block. reading nginx documentation it is the right way to do stuff. they only warn bad practice from not having a default root outside all locations.… – guy mograbi Sep 27 '15 at 10:22
Well, it is easier to have a rule of thumb not to use root inside a location block, then you won't get any unexpected behavior for default locations. Only if you need to change the default root for each location, then you can use it. – Tero Kilkanen Jan 19 at 16:59

You should use URI part in proxy_pass directive. Also, you mixed up order arguments of proxy_redirect directive, and probably you don't need it at all. Nginx has reasonable default for this directive.

In this case your location block could be really simple:

location /some/path/ {
    # note this slash  -----------^
    proxy_set_header Host $host;
share|improve this answer
Apologies for the late reply - I tried this out and unfortunately it doesn't work for our use-case. The issue is that, when the request is made on the target server, the /some/path/ part of the URL is preserved in the request which is not a valid URL (we need to rewrite the URL as well to remove this). – robjohncox Apr 24 '14 at 9:21
@robjohncox what exactly did you try? – Alexey Ten Apr 24 '14 at 9:42
the slash did the trick for me. Now* is proxied correctly to* and not* – Vadimo Nov 18 '14 at 11:51
Can I upvote the "# note this slash" comment in this response? Three cheers for that comment! – 8one6 Jan 12 at 15:53

Your Answer


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.