10

I am looking to reverse proxy one url/path to different ports on an end point that represent different servers hosting their own web apps.

I have the proxy_pass working, but the static files fail because the resources are relative their instance.

I have for example - server_name = myproxy.com:

location /app1/{
    proxy_pass: http://192.168.1.1:8080/;
    proxy_set_header Host 192.168.1.1;
}
location /app2/{
    proxy_pass: http://192.168.1.1:8081/;
    proxy_set_header Host 192.168.1.2;
}
location /{
    proxy_pass: http://192.168.1.1:8080/;
    proxy_set_header Host 192.168.1.1;
}

The reverse-proxy works great as mentioned, except for the static files associated with the app2. App1 static files work fine, but App2 static files result in a 404. Which make sense, because App1 resource files are located at /assets/app1.css this works because I have a redirect for location / in place that resolves back to App1 but App2 resource files, which are totally different /assets/app2.css result in 404.

So, is there a way to rewrite App2 static requests from /assets/app2.css to their respective proxy location? something like:

location /app1/{
    proxy_pass: http://192.168.1.1:8080/;
    proxy_set_header Host 192.168.1.1;
}
location /app2/{
    proxy_pass: http://192.168.1.1:8081/;
    proxy_set_header Host 192.168.1.2;

    *rewrite app2 static urls frome /assets/* to /app2/assets/*
}
location /{
    proxy_pass: http://192.168.1.1:8080/;
    proxy_set_header Host 192.168.1.1;
}
abarraford
  • 655
  • 2
  • 7
  • 23
  • Do you want to rewrite links in html body? If yes, try this http://nginx.org/en/docs/http/ngx_http_sub_module.html But check that your backend do not gzip files. – Dmitry MiksIr Apr 26 '16 at 00:10

2 Answers2

9

When a file /assets/app1.css(App1) load by rules from location /app1/ then load as /assets/app1.css by rules from location /. App2 has same behavior, but you location / was configurate for App1, not for App2.

Your config must be:

location /app1/ {
    proxy_pass: http://192.168.1.1:8080/app1/;        
}

location /app2/ {
    proxy_pass: http://192.168.1.1:8081/app1/;      
}

Required: The alias app1 should be is same on proxy and upsteam servers. On upsteam server it may been symlink to original webroot application.

Or you can use different subdomain or ports....

server_name app1.localhost;
location / {
    proxy_pass: http://192.168.1.1:8081/;      
}

P.S.

I explored many manipulations with nginx config by proxy. Nginx doesn't work correctly with one rule:

location /app1/ {
    proxy_pass: http://192.168.1.1:8080/;        
}

For example: css and js files will be load - proxy_server/css ... - proxy_server/js ...

from request proxy_server/app1/index.html and you will get 404.

You can add location /css/ rule to config. But your app2 could use this location too. And you can't detect upstream server to proxy by him. You can use reffer to detect upsteam

 server {
    listen          80;

    if ($uri ~ app1/) {
      break;
    }

    if ($http_referer ~ app1/ ) {
      rewrite (.*) /app1/$1 redirect;
    }

    location /app1/ {
        proxy_pass http://192.168.1.1:8080/;
    }
}

but POST data will be destroy after redirect.

It would be great if it was necessary to adjust the configuration only to the proxy server by location. But it's a dream.

Evgeniy Tkachenko
  • 1,733
  • 1
  • 17
  • 23
  • 1
    thanks for the response. I ended up going the easier route, which was to open up multiple ports to Nginx, then I created a separate nginx configuration for each service. accessing app1 became server_url:8081 and accessing app2 became server_url:8080 and so on, letting me skip having to deal with any of these 404 errors. This works for me because this is supporting an internal only platform. It would not be ideal for something public facing. – abarraford Jan 31 '18 at 15:32
  • @user3263752 could you share your config file content? – alayor Jul 08 '19 at 13:50
  • I have one nginx.conf file that is the main conf file, this looks similar to the example conf here: https://www.nginx.com/resources/wiki/start/topics/examples/full/, except I do not have any server blocks inside mine but I do have an `include path/to/app/confs/*.conf`. Now I can create any number of server block configurations inside separate conf files. Some might support WebSockets, some plain http, https, some with lua authentication . . . you name it, each of these subsequent conf files are associated with a specific back end service and routed separately by bound Nginx ports. – abarraford Jul 09 '19 at 00:12
0

I encountered this problem too when I was using docker container links to connect my containers like in some of the older documentation. Docker container networking is the thing to use

Fails to get the url context correctly giving 404 errors

docker run --name nginx-ss-00.starbug.com --link aai-gunicorn-00:aai-gunicorn-00 -d -p 80:80 -p 443:443 nginx-ss.starbug.com

but I finally found this tutorial on connecting multiple web sites. This is what worked for me:

docker network create nginx-proxy

docker run --net nginx-proxy --name nginx-ss-00.starbug.com -v /var/run/docker.sock:/tmp/docker.sock -d -p 80:80 -p 443:443 nginx-ss.starbug.com

docker run --net nginx-proxy --name aai-gunicorn-00 -d -p 8080:8080 aai-gunicorn

and in my nginx conf

server {

    server_name  www.starbug.com;
    listen       80;

    # reverse proxy
    location / {

        # TODO Assumes flask container is named aai-gunicorn-00 and running on port 8080
        proxy_pass http://aai-gunicorn-00:8080;

        # Redefine the header fields that NGINX sends to the upstream server
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        client_max_body_size 5M;

    }

}

This is running my website www.starbug.com which has links to my git repo with the full example.