//------------------------------------------------------------------- //-------------------------------------------------------------------
Nginx proxy manager troubleshooting

Nginx Proxy Manager Production Issues: Fix 502, Redirect Loops, and Cert Renewal Failures

Nginx proxy manager troubleshooting is not always straightforward; the same 502 error can have five different root causes. This article shows every real failure after the initial deployment and its fixes:

  • 502 and 504 errors
  • Broken WebSockets
  • DNS problems
  • Redirect loops
  • Certificate renewal failures

If you want to deploy NPM with Docker Compose, you can check the Nginx Proxy Manager Docker Compose setup guide before diving into the fixes.

Nginx Proxy Manager Troubleshooting: Check the Logs First

Before changing any settings or configs, you must pull the logs first. Most errors tell you exactly what is wrong.

First, use the command below to see the live container logs:

docker logs -f <npm-container-name>

If you don’t know the container name, use the command below to find it:

docker ps

Inside the container, you can check a specific proxy host error log with the commands below:

docker exec -it <npm-container-name> bash
cat /data/logs/proxy-host-1_error.log

Each proxy host has its own access and error log stored at:

/data/logs/proxy-host-<id>_access.log
/data/logs/proxy-host-<id>_error.log

The number in the filename matches the proxy host ID shown in the NPM dashboard. Always start here; the log usually tells you the cause within the first few lines.

Now you can proceed to the following steps to start Nginx proxy manager troubleshooting.

1. Fix 502 Bad Gateway Errors

The 502 error is the most common thing you will see after setting up a new proxy host. In Nginx Proxy Manager troubleshooting, a 502 error almost always means NPM cannot reach the upstream service.

Wrong container port in the forward field

The most common mistake is putting the host port in the Forward Port field instead of the container’s internal listening port.

For example, if your docker-compose.yml maps -p 49152:80, your container listens on port 80 internally. NPM talks directly to the container, not to the host, so you must enter 80 in the forward port field, not 49152.

NPM and the target container are on different Docker networks

If NPM cannot resolve the container hostname, it will throw a 502. This happens when NPM and your app container are on separate Docker networks.

To fix it, you must put both containers on the same custom Docker network:

# In your docker-compose.yml for each service
networks:
  proxy-net:
    external: true

# Create the network once
docker network create proxy-net

Then, in your NPM proxy host, use the Docker service name as the forward hostname, not localhost. Using localhost points to the NPM container itself, not your app.

Wrong scheme selected | HTTP vs HTTPS

If your upstream service does not have its own SSL certificate, set the scheme to HTTP in the NPM Details tab. Only set it to HTTPS if the backend container is actually serving HTTPS. The SSL certificate for the public domain goes in the SSL tab; it is separate from the backend connection scheme.

The container is not running or is not ready

Sometimes the upstream container crashed or hasn’t finished starting yet. Run the commands below to check:

docker ps -a
docker logs <your-app-container>

If the container exited, fix the app error first before changing the NPM configs.

Using multiple domains in one proxy host

If you list multiple domains in one proxy host and get a 502, you must add this to the Advanced tab in NPM:

proxy_ssl_name $host;
proxy_ssl_server_name on;

2. Fix 504 Gateway Timeout Errors

A 504 is different from a 502. A 502 means NPM could not connect to the backend. A 504 means the connection was made, but the backend took too long to respond.

The error in the logs looks like:

upstream timed out (110: Connection timed out) while reading response header from upstream

The fix for slow backends is to add custom timeout values in the Advanced tab of your proxy host:

proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;

You can increase proxy_read_timeout for services that do heavy processing, like AI inference, report generation, or large file uploads. The default is 60 seconds, which is too short for many production workloads.

If 504 errors are caused by a VPS that’s underpowered for your workload, it may be time to upgrade your server. PerLod has scalable Linux VPS plans that can handle heavier upstream processing without timeout issues.

3. Fix Broken WebSocket Connections

WebSocket errors usually show up as connections that open and then drop immediately, or apps that need real-time updates, like dashboards or chat tools, that don’t work. When doing nginx proxy manager troubleshooting for WebSockets, the fix is usually one toggle.

Enable WebSocket support in NPM

Open the proxy host, go to the Details tab, and enable WebSocket Support. This adds the required upgrade headers automatically.

If enabling the toggle does not fix it, add these lines manually in the Advanced tab:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Important Note: These headers must be in the location block, not the server block. Putting them in both places will break WebSocket support.

NPM version bug with WebSockets

Versions 2.9.0 and 2.9.1 had a bug where WebSocket headers were placed outside the location block, making them ineffective. If you are on an older version:

  • Open the proxy host in NPM.
  • Disable WebSocket support, save.
  • Re-open and enable WebSocket support, save again.

This forces NPM to regenerate the config correctly. A better option is to update to the latest image:

docker pull jc21/nginx-proxy-manager:latest
docker-compose up -d

4. Fix Wrong DNS Records

Before nginx proxy manager troubleshooting can solve most errors, the DNS must be correct. If your DNS records are wrong, you’ll get connection failures, certificate errors, and 502s that look like NPM bugs but aren’t.

Verify your DNS is pointing to the right IP

Check an A record with:

dig A yourdomain.com +short

Check from a public DNS resolver:

nslookup yourdomain.com 8.8.8.8

The IP returned should match your server’s public IP. If it doesn’t, update the A record in your DNS provider’s dashboard and wait for propagation.

If using Cloudflare, watch the proxy mode

If you are behind Cloudflare and have the orange cloud (proxied) enabled, set the Cloudflare SSL/TLS mode to Full, not Flexible. Flexible causes a redirect loop because Cloudflare connects to your server over HTTP, but NPM redirects HTTP to HTTPS, creating an endless loop.

Also, when requesting a Let’s Encrypt certificate via HTTP-01 challenge with Cloudflare proxying on, temporarily switch the record to DNS Only (grey cloud) during certificate issuance, then re-enable the proxy.

5. Fix Redirect Loops

A redirect loop, like Too many redirects or ERR_TOO_MANY_REDIRECTS, in the nginx proxy manager troubleshooting usually means one of these things:

Cause 1: Cloudflare SSL mode is set to Flexible

To fix this, set it to Full in Cloudflare Dashboard > SSL/TLS > Overview.

Cause 2: Force SSL is enabled in NPM, and the upstream is already redirecting to HTTPS

You must disable Force SSL in the NPM SSL tab for that proxy host. If your backend is already serving HTTPS and NPM is also forcing a redirect, the request bounces back and forth.

Cause 3: The scheme is set to HTTPS, but the backend doesn’t have a cert

For this, you must change the forward scheme back to HTTP in the Details tab.

6. Fix Failed HTTP-01 Certificate Validation

Let’s Encrypt uses the HTTP-01 challenge to verify you own a domain. It requests:

http://yourdomain.com/.well-known/acme-challenge/

If anything blocks this, the cert request or renewal fails.

Common reasons it fails:

  • Port 80 is blocked by a firewall or your hosting provider.
  • Cloudflare proxy is on and interfering with the challenge path.
  • Another service is using port 80 on the same server.

Check if port 80 is open

From a remote machine or tool, run:

curl -I http://yourdomain.com

Check what is using port 80 on the server:

sudo lsof -i :80
sudo ss -tlnp | grep :80

If something else is on port 80, stop it first. NPM needs port 80 exclusively for HTTP challenges and HTTP-to-HTTPS redirects.

Switch to DNS-01 Challenge if port 80 is unavailable

If you cannot expose port 80, use the DNS Challenge instead. In NPM, when requesting a certificate:

  • Enable Use a DNS Challenge.
  • Select your DNS provider.
  • Enter the API credentials.

For Cloudflare, the API token needs Zone: DNS: Edit permissions for the domain zone.

7. Fix Certificate Renewal Failures

Automatic renewal in NPM runs through certbot in the background. The problem is that NPM shows the cert as valid in the UI even when renewal is silently failing. The only way to catch it is to check the logs.

Check renewal logs inside the container

docker exec -it <npm-container-name> bash
cat /var/log/letsencrypt/letsencrypt.log

Or from the host:

docker logs <npm-container-name> 2>&1 | grep -i "certbot\|renew\|error\|failed"

A failed renewal shows:

Failed to renew certificate npm-X with error: Some challenges have failed.

Common renewal failure causes and fixes

CauseWhat You SeeFix
Port 80 blockedTimeout during connect (likely firewall problem)Open port 80 or switch to DNS-01 challenge
DNS challenge credentials expiredUnable to locate credentials or Invalid request headersRefresh the API token in NPM SSL settings
DNS propagation too slowDNS problem: NXDOMAINAdd Propagation Seconds: 60 in DNS challenge settings
Cloudflare proxy blocking challengeChallenge times outTemporarily disable Cloudflare proxy (DNS only mode)

Force a manual renewal

If auto-renewal is stuck, you can trigger a renewal manually:

  • Go to SSL Certificates in the NPM dashboard.
  • Click the three-dot menu next to the cert.
  • Click Renew Certificate.

If that fails with an internal error, check the letsencrypt log inside the container as shown above. The log will show the exact certbot error. You also can read the related docs from the Let’s Encrypt Community for more edge cases and validation errors.

8. Fix Proxy Headers and Real IP Issues

When nginx proxy manager troubleshooting includes apps that are logging the wrong IP or breaking because they can’t see the real client IP, the fix is in the proxy headers.

Add these to the Advanced tab of your proxy host:

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

NPM sets some of these by default, but certain apps, like Nextcloud, Authentik, or Gitea, need all four headers to be set.

If you are behind Cloudflare, the real client IP comes in the CF-Connecting-IP header from Cloudflare, not in X-Forwarded-For. You can trust it by adding:

real_ip_header CF-Connecting-IP;
real_ip_recursive on;

Validate Container Networking Step by Step

When in doubt about whether NPM can reach your container, you can test it directly.

1. Find the NPM container name:

docker ps

2. Get a shell inside NPM:

docker exec -it <npm-container-name> bash

3. Test if the upstream is reachable from inside NPM:

curl -v http://<service-name>:<internal-port>

4. Check which networks NPM is connected to:

docker inspect <npm-container-name> | grep -A 20 '"Networks"'

5. Check if your app is on the same network:

docker inspect <app-container-name> | grep -A 20 '"Networks"'

If the curl from inside the NPM container fails, the networking is the problem, not the proxy host config. Both containers need to share the same Docker network, and you should use the Docker service name as the forward hostname, not localhost or 127.0.0.1.

Conclusion

Most nginx proxy manager troubleshooting problems depend on a small set of root causes, including:

  • Wrong container networking
  • Incorrect forward port
  • Missing WebSocket headers
  • Blocked port 80
  • DNS is pointing to the wrong IP

The fixes are rarely complex, but you need to check the right place first. Start with the logs, validate the network, then work through the proxy host settings. With the error fixes in this guide, you should be able to resolve any production issue in minutes.

Also, if you are comparing NPM to other proxy solutions, you can see this guide on fixing common Traefik errors and how similar issues look in Traefik.

We hope you enjoy this Nginx proxy manager troubleshooting guide.

FAQs

Why does NPM show 502 even though my container is running?

Because your container is on a different Docker network than NPM, or you’re using the wrong port. Make sure both containers share the same network and the forward port is the container’s internal port, not the host port.

Why does my WebSocket app stop working after an NPM update?

Versions 2.9.0 and 2.9.1 had a WebSocket bug. Update to the latest image and re-save the proxy host to regenerate the config.

Can I use Let’s Encrypt if port 80 is blocked?

Yes. Switch to the DNS-01 challenge in NPM’s SSL certificate settings and provide your DNS provider’s API credentials.

Post Your Comment

PerLod delivers high-performance hosting with real-time support and unmatched reliability.

Contact us

Payment methods

payment gateway