502 Bad Gateway for nginx

I have deployed two apps. One nginx app, config below and the other app is simple api with one endpoint (normal fly.io app)

server {
  listen 80;
  server_name mydomain.com; 

  # Redirect HTTP to HTTPS
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl;
  server_name mydomain.com; 

  # SSL/TLS certificates
  ssl_certificate /etc/ssl/certs/server.crt;
  ssl_certificate_key /etc/ssl/private/server.key;

  # Additional SSL settings as needed (e.g., HSTS, TLS versions)

  location / {
    proxy_pass https://my-api.fly.dev;
    proxy_set_header Host $host;
  }

  location /static {
    # Serve static assets efficiently
    try_files $uri $uri/ /index.html;
    add_header Cache-Control "public, max-age=31536000";  # One year cache for static assets
  }
}

The certificates are correctly set up in mydomain.com and nginx conf above.

The error I see in the nginx app logs is below

333#333: *1 no live upstreams while connecting to upstream, client: 172.16.157.122, 
server: mydomain.com, request: "GET / HTTP/1.1", upstream: "https://my-api.fly.dev/", host: "mydomain.com"

When I deploy, and check mydomain.com, I get a 502 bad gateway. What am I doing wrong?

Hi,

A few things to check.

First, it looks like you are using https://my-api.fly.dev for your API. The nginx is failing to get a response back, resulting in the 502. Can you access https://my-api.fly.dev ? If you type https://my-api.fly.dev does that work?

If not, that explains the issue - if you can’t access it, nginx won’t be able to either. So you’d need to debug why the API app isn’t working. For example by running flyctl logs for that app.

If the API is running but nginx can’t access it, perhaps you have https://my-api.fly.devset to not respond to the public. No idea how that app is set up with its fly.toml. But if it is not set to respond to public requests with an exposed 443 from e.g from the tls handler provided by Fly, you would need to proxy to it from your nginx app using the private .internal domain instead. For example:

proxy_pass http://my-api.internal:8080;

(or whatever its internal_port value is set as).

The other possible issue is setting the Host header proxy_set_header Host $host :thinking: Not sure that is needed. Again, it would depend on your API and what it’s expecting.

Then try connecting to each domain and check it works as expected.

1 Like

Thanks Greg.

https://my-api.fly.dev works fine and responds to public. The fly.toml for this endpoint is below.

app = 'my-api'
primary_region = 'sin'

[build]

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0
  processes = ['app']

[[vm]]
  memory = '1gb'
  cpu_kind = 'shared'
  cpus = 1

Does the fly.toml need to change? I will try proxy_pass http://my-api.internal:3000;

I will try removing proxy_set_header Host $host

So setting proxy_pass http://my-api.internal:3000; in nginx.conf works fine. But when all machines in my-api are suspended then, the mydomain.com times out with 504.

I changed the fly.toml to min_machines_running = 1 Hope this solves it. Is there any other approach? Thanks in advance.

1 Like

Hi,

Ok, so it’s working, that’s good.

You can either proxy using the public name.fly.dev or your private name.internal one. It depends how you want it to work, whether you want the API available to requests not using custom-domain.com etc. That’s all up to you.

But yes, you will get a 502 or 504 (I always forget which is which) from nginx if it tries to proxy from the upstream (in this case the api) and doesn’t get a response within its expected time. It won’t wait forever and gives up. I would assume its request is hitting while there are 0 machines, and by the time one starts running, it has given up and returned an error code.

So yep, the solution to that would either be to keep at least one api machine running at all times or increase the nginx proxy timeout value to Xs (to allow time for one to start).

1 Like

I will try increasing the nginx timeout. I noticed that the redirect through nginx results in a delayed response. Expected I suppose.

While .internal works using name.fly.dev results in a 502 Bad Gateway right away.

Flycast - Private Fly Proxy services may help if you want to allow all machines to suspend.

Yet to try Private Fly Proxy. Thanks for pointing me to the docs.

Ok I tried Flycast - Private Fly Proxy services

Steps:

  1. Created a private IPv6 for the app
  2. Removed force_https = true from the [http_service] in fly.toml
  3. Deployed the app

In the nginx.conf of reverse proxy, I did the following

server {
  listen 80;
  server_name mydomain.com;  

  # Redirect HTTP to HTTPS
  return 301 https://$host$request_uri;
}
server {
...other code
  location / {
    proxy_connect_timeout 90s;
    proxy_pass http://my-fly-api.flycast:3000; # also tried http://[IPv6]:3000
  }
...other code
}

With this setup back to 502 Bad Gateway

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.