3

I'm attempting to set up a reverse proxy using proxy_pass in NGINX. The page loads fine but all the static assists (js, css, imgs) that use relative urls break because it prepends the host name of the parent server. Is there a way to use a reverse proxy while maintaining the proxy host name for all the static resources?

parent.conf

server {
    listen 80;
    server_name parent.mydomain.com;
    return 301 https://$server_name$request_uri;
}

server {

    listen 443 ssl;

    server_name parent.mydomain.com;
    root /var/www/parent;
    index index.html;

    try_files $uri.html $uri $uri/ =404;

    # error and access out
    error_log /var/log/error.log;
    access_log /var/log/access.log;

    ssl on;
    ssl_certificate /etc/ssl/myssl.pem;
    ssl_certificate_key /etc/ssl/myssl-key.pem;

    # Here is the important part. Any url matching 
    # this pattern needs to proxy_pass to child. 
    location ~ "^/[a-z0-9]{24}$" {

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass https://child.mydomain.com;

        proxy_redirect off;
    }

}

child.conf

server {
    listen 80;
    server_name child.mydomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443;
    server_name child.mydomain.com;
    root /var/www/child;

    ssl on;
    ssl_certificate /etc/ssl/myssl.pem;
    ssl_certificate_key /etc/ssl/myssl-key.pem;

    error_log /var/log/child.log;
    access_log /var/log/child.log;

    # this is a single page app so all request
    # should be routed through index.html.
    location / {
        try_files $uri /index.html;
    }
}

Now if I hit https://parent.mydomain.com/54570f77968d6e492b0d68af the index page from child.mydomain.com loads fine but none of my static files do since they're trying to load under https://parent.mydomain.com instead of where they are actually located https://child.mydomain.com/js/main.js.

4
  • What exactly are you asking? Can you add concrete examples of what you see, and what do you want instead?
    – cnst
    Feb 21, 2016 at 2:54
  • @cnst yes, I'll update the example.
    – jwerre
    Feb 24, 2016 at 17:30
  • so, do you just want all the requests from parent to go to the child thing? do you have anything on the parent that should not go to child?
    – cnst
    Feb 24, 2016 at 20:31
  • @cnst I don't want parent to load anything from child except the index page. I need the host for all the static resources to remain child.mydomain.com
    – jwerre
    Feb 24, 2016 at 22:32

2 Answers 2

1

Instead of reverse proxying the "ip" address (proxy_pass http://127.0.0.1:9003), try proxy_pass http://YourHostNameBehindReverseProxy:9003.

Then add YourHostNameBehindReverseProxy to /etc/hosts and associate with 127.0.0.1.

6
  • That was it! Why did that work?
    – jwerre
    Jan 22, 2016 at 19:46
  • Entry inside /etc/hosts file can be thought of static DNS. When you do reverse proxy, NGINX access the server via host name. As a result, all of your relative path would have hostname/path rather than ip/path.
    – jackluo923
    Jan 22, 2016 at 19:48
  • No, I take that that back. When I add the port to the parent address it works but not if I remove the port.
    – jwerre
    Jan 22, 2016 at 19:49
  • www.parent.com:9003/5550cdea6928495a25bb8df8 works but www.parent.com/5550cdea6928495a25bb8df8 doesn't :(
    – jwerre
    Jan 22, 2016 at 19:50
  • @jwerre Your reverse proxy listens on port 9003. If you want it to access without port number, and reverse proxy contents from localhost:9003, then you need to change the listening port to 80 (default http port).
    – jackluo923
    Jan 22, 2016 at 19:53
1

@cnst I don't want parent to load anything from child except the index page. I need the host for all the static resources to remain child.mydomain.com – jwerre 7 mins ago

Your question appears to be offtopic for serverfault, then.

Best way to accomplish what you want would then be to use the <base href='https://child.mydomain.com/'/> to ensure that the browser always loads all resources from child.mydomain.com:

<html>
   <head>
      <base href='https://child.mydomain.com/'/>

Alternatively, if you don't have anything else that you want to serve from within the parent itself, then you can simply do a 301 Moved redirect from all 404 pages to the child.

    error_page 404 =301 http://child.mydomain.com$request_uri;

Or, better yet, remove your try_files from the parent, and instead redirect all requests which don't match a more specific location to the child:

location / {
    return 301 http://child.mydomain.com$request_uri;
}
5
  • would those be added to the parent or child config?
    – jwerre
    Feb 25, 2016 at 20:56
  • @jwerre, html would have to be added to the child html source; the error_page or location -- parent; note that any one of the three should be sufficient.
    – cnst
    Feb 25, 2016 at 21:01
  • I don't think these are good solutions since they'd invalidate other resources loaded by parent. The location block might work if I can nest it. Can you nest location blocks in NGINX? something like: location ~ "^/[a-z0-9]{24}$" { location / { return 301 http://child.mydomain.com$request_uri; } }
    – jwerre
    Feb 25, 2016 at 21:08
  • best solution is the base href one i suggested above, it'll work 100%, within the constraints of your question and doesn't invalidate anything at all; you can use nested locations, but there are some restrictions, and it's just not going to work in your case that way; i wish i'd be able to give more details, but this whole question couldn't possibly be any more unclear on what is it that you ultimately want to do and what your ulterior constraints are; also, FYI, this is not a discussion board -- you're not supposed to go back and forth with brand new requirements every couple of days
    – cnst
    Feb 26, 2016 at 19:43
  • In addition to the base href suggestion above, which would be the best and most reliable option, you could also check the $http_referer variable of each request on the parent, and then, conditionally, provide redirects to the client, e.g., place the following prior to your try_files in the parent -- if ($http_referer ~ ^https://parent.mydomain.com/[a-z0-9]{24}) {return 302 http://child.mydomain.com$request_uri;}, but note that this may interfere with client caching the requests, so, it's not at all recommended.
    – cnst
    Feb 26, 2016 at 23:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .