There are a few likely causes for the 502 here. The most important one is that Stalwart’s HTTP listener defaults to port 8080, not 8081, so your proxy_pass http://127.0.0.1:8081 may simply be hitting a closed port. Also, if Stalwart’s HTTP listener has TLS enabled (i.e. it is listening on HTTPS rather than plain HTTP), NGINX’s plain http:// upstream will get a TLS handshake where it expects plain HTTP, causing the “upstream prematurely closed connection” error.
Here are the things to check and fix:
Confirm the correct port. Stalwart’s default plain-HTTP listener is on port 8080, not 8081. Verify the actual port your Stalwart instance uses (check your NetworkListener settings in the WebUI or via stalwart-cli), then update proxy_pass accordingly:
proxy_pass http://127.0.0.1:8080;
Make sure you are pointing at the plain HTTP listener, not the HTTPS one. The docs recommend the HTTP-upstream pattern for simplicity: NGINX terminates TLS for clients and forwards plain HTTP to Stalwart’s HTTP listener on port 8080. If your Stalwart listener has TLS/implicit TLS enabled, you must either switch to an HTTP listener for the backend, or configure NGINX with https:// upstream and certificate verification.
Set STALWART_PUBLIC_URL. Because NGINX is terminating TLS but Stalwart sees plain HTTP internally, Stalwart needs to know the public URL so that its OAuth/OIDC/JMAP discovery documents emit correct https://... absolute URLs. Set the STALWART_PUBLIC_URL environment variable to https://mail.domain.dk.
Auto-ban risk. Without the Proxy Protocol or X-Forwarded-For trust configured, Stalwart may auto-ban the loopback/proxy address after a few failed login attempts. The docs recommend configuring the X-Forwarded-For trust (useXForwarded on the HTTP listener) or the Proxy Protocol, and adding the proxy’s IP to proxyTrustedNetworks in SystemSettings.
The full NGINX guide (including a TCP-passthrough example using stream {}) is at: NGINX | Stalwart
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
I did, yes, thank you. I am still getting 502 bad gateway. And I can’t really fix a 502 error with a tool that depends on not getting a… 502 error.
So I reinstalled my Stalwart server and restored its contents. I then enabled getting client ID from HTTP headers using the WebUI… Then a few hours later I get 502 bad gateway again…