2

I have a server on which I've deployed an API (Sinatra). I run that API on port 9292 and proxy requests to it.

I also need to deploy a static javascript file and its supporting resources. I do that on the same server.

All of the information below has been anonymized.

The API access endpoint is this:

server {
    listen 80;
    server_name api.myapp.com;

    location / {
            proxy_pass http://localhost:9292;
    }
}

and the endpoint I'm serving the JS from is:

server {
    listen 80;
    server_name xsa.myapp.com;

    location / {
            root /data/mydir/xsa;
    }
}

The "localhost:3003" server that you see in the error below is where I am referring to the JS from.

2018/11/23 23:31:27 [error] 18720#0: *32 connect() failed 
(111: Connection refused) while connecting to upstream, 
client: 255.255.255.7, server: api.myapp.com,
request: "GET /api/v1/sub/sub_ABCXYZ/info?token%3D56f51132-
406b-4e06-a600-7379876446ed HTTP/1.1", upstream:
"http://[::1]:9292/api/v1/sub/sub_ABCXYZ/info?token%3D56f51132
-406b-4e06-a600-7379876446ed", host: "api.myapp.com",
 referrer: "http://xsa.myapp.com/src/selector.html?
mfid=sub_ABCXYZ&location=http://localhost:3003/"

So to recap:

  • Sinatra API on VM "x" with port 9292
  • nginx server on VM "x" serving up a proxy on port 80 to the API for requests coming in to "api.myapp.com"
  • same nginx server also serving up a javascript file on port 80 for requests coming in to "xsa.myapp.com"

I can view the JS just fine in a browser, so it is indeed being served up. It is in the dynamic stuff it does upon instantiation that is causing the error.

I can also see that the Sinatra server on 9292 is indeed getting the request and returning a 200. It appears that the problem is after this then. So it doesn't even look like the upstream connection is actually refused. I have double-checked that this reply is the exact same response as when the JS is served up locally (and works).

* UPDATE *

The "connection refused" error actually DOES occur even when the JS is served locally and works correctly, so it looks like that error is a red herring.

AKWF
  • 481
  • 2
  • 6
  • 17

1 Answers1

2

You're getting this error message because your Sinatra application is not listening on the default IPv6 address for localhost, ::1, but is instead listening on the legacy IPv4 address, 127.0.0.1.

Because you specified that your nginx upstream is localhost, nginx tries the IPv6 address first, but because your app server isn't listening on this address, nginx gets a Connection refused. It then retries the connection on IPv4, which succeeds, and serves your application.

Because this introduces a performance problem, and because IPv6 is preferred over the deprecated IPv4, you should reconfigure your Sinatra application to listen on IPv6. For example,

set :bind, '::1'

In particular, you should not bind to 127.0.0.1.

You can also just remove the bind host, because by default it will listen on IPv6 localhost if you're using thin (as you should in prod) or WEBrick (in dev, if you forget to gem install thin).

(And on a related note, you have explicitly configured nginx to not listen on IPv6, which will cause you similar problems later on, or perhaps even now. You should fix that too, while you're at it.)

Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
  • I'm just trying to run it with rackup. Unfortunately I don't have any time to learn about thin or really even Sinatra at the moment. When I run this command: bundle exec rackup config.ru all I know is that it runs Webrick on 9292 regardless of what you put in your app.rb file. I assume that command you listed goes in app.rb. Even the Sinatra docs, while listing all of the possible configuration attributes, don't even tell you the file they go in. Which is weird. – AKWF Nov 27 '18 at 20:13
  • 1
    My guess is that you'll find the bind host set wherever the port is also set. It must be set somewhere, as the default Sinatra port is 4567, not 9292. A quick `grep` should find it. – Michael Hampton Nov 27 '18 at 20:50
  • @MichaelHampton I'm getting the same error as above on my Nginx server that has both ipv4 and ipv6 provisioned. Since you mentioned that `It then retries the connection on IPv4, which succeeds, and serves your application.`, I'm not as worried with the errors anymore but since `this introduces a performance problem`, what would be the right way to avoid the above while still using ipv6 along with ipv4? – AndrewL64 Jun 25 '21 at 14:44
  • @AndrewL64 Follow the directions given in the answer. – Michael Hampton Jun 25 '21 at 15:07
  • I'm encountering this error on an Nginx server that doesn't have Sinatra. I am hosting a few WordPress sites on them and using Virtualmin+Webmin to manage the virtual hosts and server. What would be the right way to fix this without having to remove ipv6? – AndrewL64 Jun 25 '21 at 16:32