10

I need these two types of rewrites:

subdomain.domain.com => domain.com/website/subdomain

otherdomain.com => domain.com/userdomain/otherdomain.com

My problem is that I want the user to see subdomain.domain.com, and otherdomain.com, not the redirected version. My current rewrite in nginx works, but the user's URL shows the rewrite, and I want this to be transparent to the user, any ideas?:

upstream domain_server { server localhost:8000 fail_timeout=0; }     

server {
        listen  80;
        root  /var/www/domain.com;

        server_name domain.com ~^(?<subdomain>.*)\.domain\.com$ ~^(?<otherdomain>.*)$;
        if ( $subdomain ) {
                rewrite ^ http://domain.com/website/$subdomain break;
        }
        if ( $otherdomain ) {
                rewrite ^ http://domain.com/userdomain/$otherdomain break;
        }

        location / {
                proxy_redirect off;
                proxy_buffering off;
                proxy_set_header Host $http_host;
                proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for;
                if (!-f $request_filename) {
                        proxy_pass http://domain_server;
                        break;
                }
        }

}
pyramation
  • 1,631
  • 4
  • 22
  • 35
  • found something interesting here: http://blog.martinfjordvald.com/2011/02/nginx-primer-2-from-apache-to-nginx/. It says "Another thing about Nginx rewrites is that by default they are internal rewrites, which means that they won’t change the URI the browser sees. They will only do that if you specify the “redirect” or “permanent” rewrite flag or if you rewrite to an absolute URL including the http:// part.". Trying to use this to come up with a solution... – pyramation May 10 '12 at 23:36

1 Answers1

29

With nginx you don't need rewrites at all.

upstream domain_server { server localhost:8000 fail_timeout=0; }

proxy_set_header Host domain.com;
proxy_set_header X-forwarded-for $proxy_add_x_forwarded_for;

server {
    listen  80 default_server;

    location / {
        proxy_pass http://domain_server/userdomain/$http_host;
    }
}

server {
    listen  80;
    server_name domain.com;

    root  /var/www/domain.com;

    location / {
        try_files $uri @backend;
    }

    location @backend {
        proxy_pass http://domain_server;
    }
}

server {
    listen  80;
    server_name ~^(?<subdomain>.+)\.domain\.com$;

    location / {
        proxy_pass http://domain_server/website/$subdomain$request_uri;
    }
}
Jeroen Ooms
  • 31,998
  • 35
  • 134
  • 207
VBart
  • 14,714
  • 4
  • 45
  • 49
  • Thanks for the great response, however, /var/www/domain.com/userdomain/$host doesn't exist, but the URL domain.com/userdomain/$host does. The idea was to transparently proxy the user to that URL when they use their own domain that is pointed to the server – pyramation May 11 '12 at 20:34
  • using proxy_pass still redirects the browser URL, I'm still trying out different configurations with this... – pyramation May 15 '12 at 20:45
  • So, probably, it's on the application side now. Your application must know how to generate appropriate links. – VBart May 16 '12 at 00:41
  • I just spawned a new instance and used apache to replicate this domain configuration and have no problems with the same application. So it's definitely the nginx conf for sure. Still working on it :) – pyramation May 17 '12 at 01:54
  • Could you provide dubug log, or, at least, equivalent apache configuration? I expect that you missed something, like slash at end of URIs. – VBart May 17 '12 at 08:35
  • I posted an apache solution as an answer to this question here: http://stackoverflow.com/questions/10557590/multiple-domain-hosting-with-one-django-project/10558314 – pyramation May 17 '12 at 20:40
  • Ok. In your apache config you rewrite to `domain.com/userdomain/otherdomain.com/` but not to `domain.com/userdomain/otherdomain.com` like you mentioned in question. So, just add slashes to proxy_pass: `proxy_pass http://domain_server/userdomain/$http_host/;` and `proxy_pass http://domain_server/website/$subdomain/;`. – VBart May 18 '12 at 11:07
  • that fixed it! I edited the post to add the slashes. Thanks a million! – pyramation May 18 '12 at 20:32
  • 2
    another addition may be to add `$request_uri` so it becomes `http://domain_server/website/$subdomain$request_uri/` – pyramation May 18 '12 at 20:41
  • why am I getting `invalid host in upstream: http://domain_server` could you tweak your code a bit to a noob friendly one? Thanks. – Jürgen Paul Jul 30 '12 at 15:20
  • It's already noobiest one. It may be used just by copy-n-paste into `http { }` section. You're probably doing something wrong. And I can't help until I don't know what you're doing. – VBart Jul 30 '12 at 17:36
  • @Vbart please [check this question](http://stackoverflow.com/questions/11724338/map-subdomain-requests-to-a-controller). – Jürgen Paul Jul 30 '12 at 20:26