502 Bad Gateway issue

Hi all,

I’m hoping for some guidance on a 502 Bad Gateway issue that I’ve narrowed down quite a bit, but I’m stuck on the final piece since it seems to be happening outside the server I actually manage.

Setup:

  • Self-hosted Frappe/ERPNext bench on a KVM VM (Ubuntu 24, 4 vCPUs, 3.8GB RAM)

  • Local stack: nginx → gunicorn (9 gevent workers) + node socket.io, managed via supervisor

  • The domain (let’s call it example-staging.mydomain.org) sits behind a separate front-end reverse proxy running openresty (a different server, not one I have direct access to)

Symptom: Loading the site intermittently returns:

502 Bad Gateway
openresty

Sometimes the root path works, sometimes it doesn’t — it seems intermittent rather than constant.

What I’ve verified so far on my own backend server:

  1. curl -I http://127.0.0.1 (local, bypassing the domain/proxy entirely) → consistently returns HTTP/1.1 200 OK, fast, no issues.

  2. sudo supervisorctl status → all processes (gunicorn/frappe-web, node-socketio, redis-cache, redis-queue, schedule, short-worker, long-worker) show RUNNING, no crashes, no restarts (aside from ones I triggered myself while testing).

  3. No errors in gunicorn’s own log (web.error.log) — clean startup, no worker crashes, no OOM kills.

  4. The key piece: I ran sudo tail -f /var/log/nginx/error.log locally and left it running, then immediately made a request to the public domain (using curl --resolve to hit the known front-end IP directly). The public request returned a fresh 502 from openresty — but no new line appeared in my local nginx error log at all, at that exact timestamp. I repeated this a few times with the same result: consistent 502 on the public request, consistent silence in my local logs.

My interpretation: since my local nginx logs every request it receives (successful or failed), and it logged nothing during a confirmed 502 response, it seems like the request is failing before it ever reaches my backend — i.e., the issue is on the openresty front-end’s side (upstream config, health check, or network path to my server), not in my Frappe/gunicorn/nginx stack.

My question: does this reasoning sound right to those more experienced with multi-layer reverse proxy setups (openresty/nginx in front of a Frappe bench)? Specifically:

  • Are there common openresty-side misconfigurations (upstream health checks, keepalive settings, stale backend IP) that would cause this exact “silent” 502 pattern?

  • Is there a way to add additional logging/tracing on my end that could shed more light, even though the failure seems to originate upstream of my server?

  • Has anyone dealt with a similar setup (Frappe bench behind an external openresty/nginx load balancer) and run into intermittent 502s like this?

Happy to share more logs/config if useful. Thanks in advance for any pointers!

hey @Alfiya_Hussain
can you mention your installation method? I have some experience on Docker/Podman area but haven’t worked on another way of ERPNext deployment.

Hi @elhananjair

This is a manual bench installation (not Docker/Podman) — set up directly on an Ubuntu 24 VM (KVM guest, 4 vCPUs). Stack details:

  • Frappe/ERPNext installed via bench init directly on the host, not containerized

  • Process management via supervisor (not systemd units directly) — managing gunicorn (9 gevent workers), node socket.io, redis-cache, redis-queue, and the frappe scheduler/workers

  • Local nginx in front of gunicorn (bench-generated config in sites-enabled/conf.d)

  • The public domain sits behind a separate external openresty reverse proxy on a different server, which I don’t have direct access to — that’s the specific 502 source I’m trying to narrow down

Hi @Alfiya_Hussain

Try these two - you might get some extra clues: -

sudo tail -f /var/log/nginx/access.log

sudo tcpdump -nn host example-staging.mydomain.org and port 80

Best of luck

It was due to fail2ban . I disabled it and then it worked.