Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiple django apps with nginx proxy_pass and rewrite

I have a single django-admin app named myapp that I would like to deploy multiple instances of on different physical boxes, one per customer. However, I'd like them all to be accessed from a similar domain, mydomain.com/customer1/myapp.

I've fiddled with specific proxy settings and tried multiple things suggested on SO, but none quite fit my use case... and since I know very little about both nginx and django I am at a loss!

My current nginx.conf is:

server {
    listen 80;
    server_name myserver.com

    location ^~ /static {
        alias /path/to/static/files/;
    }
#    location / {
#        proxy_pass http://127.0.0.1:8001;
#    }
    location ^~ /customer1/myapp/static {
        alias /path/to/static/files/;
    }
    location /customer1/myapp {
        rewrite ^/customer1/myapp/(/?)(.*) /$2 break;
        proxy_pass http://127.0.0.1:8001;
    }
}

I can get to the login screen as expected via myserver.com/customer1/myapp/admin. However when I attempt to log in, nginx rewrites my url to myserver.com/admin which isn't a valid url. How do I keep nginx from actually rewriting the url and only change the url that is passed on to 127.0.0.1:8001?

FWIW, I am using gunicorn to serve with gunicorn -b 127.0.0.1:8001 -n myapp. If I uncomment the / location and remove the last two location blocks, the app works great.

I am far from set on this approach if there are alternatives. The goal is to avoid modifying django code for each deployment and instead just add minimal code to the nginx.conf for new deployments.

like image 733
Justin Avatar asked Sep 10 '12 23:09

Justin


2 Answers

basically, you specify url as part of the proxy_pass directive, the following location directive should do it:

location ~ ^/customer1/myapp(/?)(.*) {
    proxy_pass http://127.0.0.1:8001/$2;
}

see http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass for the detailed explanation on how nginx passes the uri

like image 69
cobaco Avatar answered Nov 10 '22 11:11

cobaco


You should use the following:

location /customer1/myapp {
    return 302 $uri/;
}
location /customer1/myapp/ {
    proxy_pass http://127.0.0.1:8001/
}

Note that this is superior to using variables within proxy_pass, because if you do use variables, then proxy_redirect can no longer be of the default value default, and will be off instead, and then internal 302 redirects within your app will not be mapped to /customer1/myapp/ after being fetched by nginx, which will likely cause you troubles and more 404s.

And, yes, using individual domains for individual customers is a better idea, because it's more secure (as far as cookie handling is concerned, for example).

like image 40
cnst Avatar answered Nov 10 '22 12:11

cnst