Desperately need help on Nginx!

I just started learning Nginx today and have been googling how to solve my problem for like a few hours. But I still can’t find a solution.

Here’s my requirement, I have two apps hosted on two different servers. App A on server A with nginx installed and app B on server B.

For /, app A should be served. For /hello, app B should be served.

Here’s my nginx conf:

server {
  listen 80;
  server_name SERVER_A_IP_ADD;
  access_log /var/log/nginx/app.dev.access.log;
  error_log /var/log/nginx/app.dev.error.log;

  location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_pass http://127.0.0.1:3002;
  }

  location /hello {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_pass http://SERVER_B_IP_ADD;
  }
}

Whenever I go to /hello, I keep getting:

http://SERVER_A_IP_ADD/0d6e1cba63a1fd248614caaf844e34560688ad32.js?meteor_js_resource=true Failed to load resource: the server responded with a status of 404 (Not Found)

Any guidance would be much appreciated!

@skaxwng I believe you can fix this by use of proxy_bind as so

If your proxy server has several network interfaces, sometimes you might need to choose a particular source IP address for connecting to a proxied server or an upstream. This may be useful if a proxied server behind NGINX is configured to accept connections from particular IP networks or IP address ranges.

Specify the proxy_bind directive and the IP address of the necessary network interface:

location /app1/ {
proxy_bind 127.0.0.1;
proxy_pass http://example.com/app1/;
}

location /app2/ {
proxy_bind 127.0.0.2;
proxy_pass http://example.com/app2/;
}

@tomtom87, thank you for your response! I tried your suggestion and the error is gone. But whenever I visit /hello, I got 502 Bad Gateway. Here’s my updated config (I just added proxy_bind to the location block):

server {
  listen 80;
  server_name SERVER_A_IP_ADD;
  access_log /var/log/nginx/app.dev.access.log;
  error_log /var/log/nginx/app.dev.error.log;

  location / {
    proxy_bind 127.0.0.1;
    proxy_pass http://127.0.0.1:3002;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
  }

  location /hello {
    proxy_bind 127.0.0.2;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_pass http://SERVER_B_IP_ADD;
  }
}

Do you have any ideas why this is happening?

@skaxwng ahh you must set proxy_bind to the SERVER_B_IP_ADD and try that.

Additionally you can look into configuration of upstreams: http://nginx.org/en/docs/http/ngx_http_upstream_module.html

@tomtom87, I updated the proxy_bind but now I got 500 Internal Server Error. Any ideas? Oh man! I didn’t know nginx was this tough!

Wouldn’t upstream module be useful if I have a pool of servers?

@skaxwng don’t worry this is normal for nginx :slight_smile: You are nearly up, Just tail the nginx error log (default location /var/log/nginx/error.log) and see what she spat out.

upstream allows you to setup a name space for each server and just makes its a little prettier. If you’re gonna add more then these two then maybe it is a easier way to manage.

@tomtom87, thanks for being so patient! I appreciate that.

Here’s what I got from the error log

2016/05/31 02:13:04 [crit] 9557#0: *1 bind(SERVER_B_IP_ADD) failed (99: Cannot assign requested address) while connecting to upstream, client: 75.72.170.8, server: SERVER_A_IP_ADD, request: "GET /oh HTTP/1.1", upstream: "http://SERVER_B_IP_ADD:80/hello", host: "SERVER_A_IP_ADD"

And here’s my config (just in case I wrote something wrong):

server {
  listen 80;
  server_name SERVER_A_IP_ADD;
  access_log /var/log/nginx/app.dev.access.log;
  error_log /var/log/nginx/app.dev.error.log;

  location / {
    proxy_bind 127.0.0.1;
    proxy_pass http://127.0.0.1:3002;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
  }

  location /hello {
    proxy_bind SERVER_B_IP_ADD;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_pass http://SERVER_B_IP_ADD;
  }
}

@skaxwng no worries… can you please verify the port 80 is open on the SERVER_B_IP_ADD and that nginx is serving directly on the ip, what happens if you try to access http://SERVER_B_IP_ADD ?

@tomtom87, when I go to http://SERVER_B_IP_ADD:80, I see my test app. One question, do I need to install nginx on my SERVER_B too?

proxy_pass is going to proxy the request to the specified server so you need to ensure http://SERVER_B_IP_ADD serves a page. You can check via curl -v http://SERVER_B_IP_ADD and see the headers.

You can serve with anything on the proxy, nginx, rails, apache, node its up to you…

yeap, I’m able to see the page.

* Connected to 162.243.21.244 (162.243.21.244) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 162.243.21.244
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Vary: Accept-Encoding
< Date: Tue, 31 May 2016 06:50:06 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked

@skaxwng everything looks good there then… the proxy returns a 500 error still yes and there is nothing in the error log? scratches head

It might be worthwhile asking in #nginx on freenode

One last thing - please run this curl -v 127.0.0.2

I got something like this:

* Rebuilt URL to: 127.0.0.2/
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.2...
* Connected to 127.0.0.2 (127.0.0.2) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 127.0.0.2
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Tue, 31 May 2016 07:00:03 GMT
< Content-Type: text/html; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
< 

I think I will start over again tomorrow. It’s 2:06 in the morning now. My brain is starting to die. Thank you so much @tomtom87 for your help!! I really really appreciate it!

1 Like

@skaxwng good idea … it seems like there is some reason the proxy cannot load the page although your tests prove it is all good. I’ve done this with PHP successfully for years, the topic is often called ‘using nginx as a load balancer’ and often uses upstream to setup each host.

I am confused as to why meteor failed at this. Hopefully someone from the MDG can help or maybe you can debug it further with a more verbose logging setting

Hope you nail it soon man!

1 Like

@tomtom87, so I added

net.ipv4.ip_nonlocal_bind=1

to allow processes to bind non-local address in my /etc/sysctl.conf. Now the 500 error is gone but 502 Bad Gateway is back.

Here’s the error log:

2016/05/31 13:41:43 [crit] 6781#0: *1 connect() to 107.170.68.167:80 failed (22: Invalid argument) while connecting to upstream, client: 75.72.170.8, server: landing, request: "GET /hello/ HTTP/1.1", upstream: "http://107.170.68.167:80/hello/", host: "107.170.121.55"

I tried to add and remove different things from the server but still didn’t solve the problem. It would be greatly appreciated if you can share with me if you came across this problem before!

Edit:

Here’s my nginx config for SERVER_A:

upstream landing {
  server localhost:3000;
}

server {
  listen 80;
  server_name 107.170.121.55;

  location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $http_host;
    proxy_pass http://landing;
  }

  location /hello/ {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_pass http://107.170.68.167;
    proxy_bind 107.170.68.167;
  }
}

and for SERVER_B:

upstream app {
  server localhost:3000;
}

server {
  listen 80;
  server_name 107.170.68.167;

  location / {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $http_host;
    proxy_pass http://app;
  }
}