Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk11 min

Nginx Reverse Proxy 502 Bad Gateway Only on HTTPS: How to Fix It

A practical guide to diagnosing NGINX 502 errors that occur only over HTTPS, with commands, log signatures and configuration patterns for protocol, certificate, SNI and network fixes.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If HTTP works through NGINX but the same URL returns 502 Bad Gateway over HTTPS, the problem is usually in the HTTPS server block or in NGINX’s separate TLS connection to the upstream. Check the active listen 443 ssl configuration, confirm that proxy_pass uses the upstream’s real protocol and port, then read the NGINX error log while reproducing one request. A public certificate that is valid between the browser and NGINX does not prove that NGINX trusts or can negotiate TLS with the backend.

What a 502 means when only HTTPS fails

A 502 response means a gateway or proxy received an invalid response from an upstream server. In a reverse-proxy deployment, NGINX is the gateway: it accepts the client request, sends a request to the configured upstream, receives the upstream response, and returns that response to the client. If the upstream sends a valid HTTP error such as 404 or 500, NGINX normally passes that response through. A 502 indicates that NGINX could not obtain a valid upstream HTTP response.

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A request that receives no response before the gateway timeout condition is reached is generally associated with 504 Gateway Timeout semantics instead. The exact status depends on what happened and which timeout or connection failure NGINX recorded, so always use the error-log line rather than the status code alone to choose a fix.

HTTPS can fail while HTTP succeeds because there are two independent connections:

  • Client to NGINX: the browser negotiates TLS with the certificate configured on the public HTTPS listener.
  • NGINX to the upstream: NGINX uses either clear-text HTTP or a second TLS session according to the proxy_pass URL.

The first handshake can be perfect while the second fails because of an untrusted private CA, a hostname or SNI mismatch, a wrong protocol, a closed port, or an upstream process that closes the connection before sending HTTP headers.

Use this troubleshooting sequence first

1. Reproduce one failing request and capture the exact log line

Keep a terminal following the NGINX error log, then make one request to the failing HTTPS URL. On many Linux installations the log is under /var/log/nginx/error.log; use the path configured by your distribution if it differs.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo tail -f /var/log/nginx/error.log
curl -vk https://public.example.com/health

Do not make several configuration changes before capturing this line. Messages such as SSL_do_handshake() failed, wrong version number, and connect() failed (111: Connection refused) identify different layers and require different remedies.

2. Test the upstream directly from the NGINX host

Run the request from the machine that runs NGINX, not from your workstation. This removes the public listener and shows whether NGINX’s host can reach the backend.

curl -vk https://backend.example.com/health
curl -v http://127.0.0.1:8080/health

Use the first form when the backend is supposed to speak TLS and the second when it is supposed to speak clear-text HTTP. Compare the result with:

curl -vk https://public.example.com/health

If the direct request fails, fix the backend listener, route, firewall, certificate, or name resolution before changing proxy headers. If it succeeds but the public request fails, inspect the effective HTTPS server block and the selected location.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

3. Inspect the configuration NGINX actually loaded

A file you edited is not necessarily the file selected for the request. Validate syntax and print the complete, expanded configuration:

sudo nginx -t
sudo nginx -T

In the output, locate the server block that handles the request’s address and hostname. Verify all of the following:

  • The block has the intended listen 443 ssl directive.
  • server_name matches the hostname sent by the client.
  • The certificate and key belong to that HTTPS virtual host.
  • The request selects the expected location rather than a more-specific location with another proxy target.
  • proxy_pass names the correct upstream scheme, hostname, port, and path.
  • Any proxy_set_header, proxy_ssl_*, client-certificate, and timeout directives are present in this block or inherited from the intended context.

After a verified change, reload rather than abruptly stopping the service:

sudo nginx -t && sudo systemctl reload nginx

4. Compare the HTTP and HTTPS server blocks line by line

Do not assume that an HTTP-to-HTTPS redirect means both requests use identical proxy settings. They may select different blocks, locations, upstream names, ports, path rewrites, or headers. Diff the two effective sections from nginx -T and check these axes:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Configuration axis What to verify Why it can create an HTTPS-only 502
Upstream scheme http:// versus https:// NGINX may send TLS to a clear-text listener, or clear text to a TLS-only listener.
Upstream port The port selected by proxy_pass The HTTPS block may point at a closed, unrelated, or differently configured service.
Upstream hostname DNS name versus IP address The name controls certificate identity, virtual-host selection, and often SNI.
Host header proxy_set_header Host ... The application may route to a different virtual host or reject an unexpected name.
TLS directives proxy_ssl_server_name, proxy_ssl_name, trust settings The upstream handshake can fail even though the public TLS handshake succeeds.
Path handling Trailing slash and URI rewrite behavior The HTTPS location may send a different path that causes the upstream to close or reject the request.
Timeouts Connect and response-header timeout values A slower HTTPS route can expose a timeout or firewall problem not seen over HTTP.

Match the upstream protocol and port

HTTPS termination at NGINX with a clear-text backend

It is valid for the browser-to-NGINX connection to use HTTPS while NGINX-to-application traffic uses clear-text HTTP on a private network. In that design, the upstream URL must use http:// and the backend must actually listen for HTTP:

server {
    listen 443 ssl;
    server_name app.example.com;

    ssl_certificate     /etc/ssl/app/fullchain.pem;
    ssl_certificate_key /etc/ssl/app/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Using https://127.0.0.1:8080 against that clear-text listener makes NGINX start a TLS handshake where the service expects an HTTP request. The usual result is an SSL error and a 502 before any HTTP headers exist.

End-to-end TLS to an HTTPS upstream

Use https:// only when the selected backend port speaks TLS. The upstream’s certificate, hostname, and trust chain then matter to NGINX:

location / {
    proxy_pass https://api.example.com;
    proxy_ssl_server_name on;
    proxy_ssl_name api.example.com;
    proxy_ssl_trusted_certificate /etc/nginx/ca/upstream-ca.pem;
    proxy_ssl_verify on;
    proxy_set_header Host api.example.com;
}

For a public certificate signed by a CA trusted by the host, the system trust store may be sufficient, depending on how NGINX was built and configured. For a private CA or self-signed certificate, point proxy_ssl_trusted_certificate at the CA certificate or bundle that issued the backend certificate. A leaf certificate copied into the wrong trust setting, an incomplete chain, or a CA file unreadable by the NGINX worker can still produce verification errors.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Conversely, changing verification off as a first response hides identity and interception problems. Treat that only as a tightly controlled diagnostic test, then restore verification and install the correct trust chain.

Fix certificate identity, hostname, and SNI

Certificate validation checks more than whether encryption is enabled. The name NGINX uses for the TLS connection must match the certificate identity, and many shared HTTPS services choose a certificate or backend using Server Name Indication (SNI).

A common failure is configuring proxy_pass https://192.0.2.10:443 when the certificate is issued to api.example.com. The address may be reachable, but certificate verification can fail because the certificate does not identify the IP address. Prefer the service hostname and enable SNI when the upstream requires it:

proxy_pass https://api.example.com:443;
proxy_ssl_server_name on;
proxy_ssl_name api.example.com;
proxy_ssl_verify on;
proxy_ssl_trusted_certificate /etc/nginx/ca/upstream-ca.pem;

Use openssl to inspect the handshake independently of NGINX:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
openssl s_client 
  -connect api.example.com:443 
  -servername api.example.com 
  -showcerts

Check the certificate subject or subject-alternative names, issuer chain, expiration, and whether the server presents a different certificate when the -servername value changes. If the upstream expects a particular HTTP virtual host as well as a TLS name, keep the application-level header aligned:

proxy_set_header Host api.example.com;

The TLS name and the HTTP Host header are related but independent. Setting one does not automatically set the other to the value your application expects.

Interpret the NGINX error log

Log signature What it usually indicates Next check
SSL_do_handshake() failed TLS negotiation, certificate, protocol, or SNI failure between NGINX and the upstream. Test with openssl s_client; verify the upstream name, port, SNI, and trust chain.
certificate verify failed The issuing CA or certificate chain is not trusted or cannot be validated. Install the correct CA bundle and confirm file permissions and hostname identity.
wrong version number NGINX is probably attempting TLS against a clear-text HTTP service, or the port is wrong. Change the scheme or port to match the backend listener and test with direct curl.
connect() failed (111: Connection refused) No process is listening at the selected address and port, or a firewall is actively rejecting the connection. Check the service bind address, listening sockets, security groups, and host firewall.
upstream prematurely closed connection The backend closed the connection before returning valid response headers. Inspect backend logs, request path, required headers, protocol expectations, and application crashes.
upstream timed out The backend or network did not respond within the configured timeout. Measure direct response time, inspect firewall and load, and adjust timeouts only after fixing reachability or latency.

These messages are clues, not interchangeable labels. For example, raising a timeout cannot repair a certificate verification failure, and disabling certificate verification cannot make a closed port accept connections.

Check network reachability and listener state

When the log reports refusal or a timeout, verify that the backend is listening on the address NGINX uses. A service bound only to 127.0.0.1 is reachable from the same host but not from a separate proxy machine. A container, virtual machine, or firewall rule can also expose a different port externally than the one used inside the network.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Confirm the route and port from the NGINX host, then inspect the backend’s own listener configuration. A successful TCP connection is not proof of a successful TLS or HTTP exchange, but a refused connection proves that NGINX cannot reach a usable service at that endpoint.

  • Verify DNS resolution from the NGINX host; split-horizon DNS can return a different address than your workstation receives.
  • Confirm that the backend process is running and bound to the expected interface.
  • Check host firewalls, cloud security groups, container networks, and service-mesh policies.
  • Ensure the HTTPS server block is not resolving a name to an old or unintended address.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Check headers, connection behavior, and URI rewriting

NGINX changes some proxy request headers by default, including Host and Connection. An application that requires the original host, a specific forwarded protocol, or a client certificate can therefore behave differently behind one location than another. Set only the headers your application needs and make the intended values explicit:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Compare trailing slashes in proxy_pass and any rewrite directives. For example, proxy_pass http://backend; and proxy_pass http://backend/; can produce different upstream URIs when used inside a location. If the backend closes a connection on an unexpected path or requires a health endpoint at a particular URI, an HTTPS-only location mismatch may appear as a 502.

Do not add arbitrary Connection: close or upgrade headers while troubleshooting. First reproduce the request with the smallest configuration that matches the application’s documented protocol.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common HTTPS-only failure patterns

The HTTPS block points to HTTP on the wrong scheme

Symptom: The error log contains wrong version number or a handshake failure, while direct HTTP to the backend returns headers.

Fix: Change proxy_pass https://... to proxy_pass http://... when the service is clear-text, or configure the backend’s actual TLS port if encryption is required.

The backend uses a private CA

Symptom: Direct curl -k works, but verification-enabled requests fail and NGINX logs a certificate verification error.

Fix: Install the issuing CA bundle, reference it with proxy_ssl_trusted_certificate, keep proxy_ssl_verify on, and verify that the certificate name matches the upstream hostname.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The upstream requires SNI

Symptom: The server is reachable, but it presents a default certificate or closes the handshake unless a hostname is supplied.

Fix: Use the service hostname, set proxy_ssl_server_name on, and set proxy_ssl_name to the certificate and SNI name expected by the service.

The HTTPS location uses a different backend

Symptom: HTTP succeeds, but nginx -T shows a different upstream group, port, or more-specific location for HTTPS.

Fix: Correct the selected server and location blocks, then reload after nginx -t passes. Test the exact path that previously failed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The application closes the connection before headers

Symptom: NGINX reports upstream prematurely closed connection.

Fix: Read the application log at the same timestamp. Check whether the HTTPS request sends a different host, forwarded protocol, authorization value, path, or body. A backend crash, rejected protocol, or missing required header must be fixed at the application or proxy boundary; increasing a timeout will not create a response that the application never sends.

Validate the repair safely

  1. Save the current configuration so you can revert a change.
  2. Make one focused change: scheme and port, trust chain, SNI, header, or location selection.
  3. Run sudo nginx -t; do not reload if syntax or referenced files fail validation.
  4. Reload NGINX and follow the error log.
  5. Test the public HTTPS endpoint with curl -vk and the exact path that failed.
  6. Test the upstream directly from the NGINX host again, using verification enabled when trust is part of the fix.
  7. Confirm that a normal application response and intentional application errors are passed through as HTTP responses rather than converted into gateway errors.

Once the request works, remove temporary debugging flags, restore normal certificate verification, and retain the configuration that documents the intended upstream protocol and hostname.

Final checklist

  • Captured one current error-log line while reproducing the 502.
  • Confirmed which server and location handle port 443.
  • Verified the proxy_pass scheme and port against the backend listener.
  • Tested reachability from the NGINX host, not only from a client device.
  • Matched the upstream certificate name, trust chain, and SNI configuration.
  • Aligned the HTTP Host header and forwarded-protocol headers with application requirements.
  • Compared HTTPS and HTTP path rewriting, upstream names, and timeout settings.
  • Validated with nginx -t before every reload.

The shortest reliable diagnosis is: identify the active HTTPS block, test the exact upstream from the NGINX host, and let the error-log signature tell you whether the failure is protocol, TLS identity, reachability, headers, or response timing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.