Introduction
Nginx is configured to proxy requests to an upstream server using proxy_pass, but the proxy connection is failing. Requests return errors like 502 Bad Gateway, 504 Gateway Timeout, or connection refused. The upstream server may be unreachable, misconfigured, or rejecting connections.
Symptoms
```bash $ curl http://localhost/api <html> <head><title>502 Bad Gateway</title></head> <body> <center><h1>502 Bad Gateway</h1></center> </body> </html>
$ tail -f /var/log/nginx/error.log 2024/01/01 12:00:00 [error] connect() failed (111: Connection refused) while connecting to upstream 2024/01/01 12:00:00 [error] connect() failed (113: No route to host) while connecting to upstream 2024/01/01 12:00:00 [error] no live upstreams while connecting to upstream
$ curl -I http://localhost/api HTTP/1.1 502 Bad Gateway
# Common error codes in logs: # (111) Connection refused - Service not running or wrong port # (113) No route to host - Network/firewall issue # (110) Connection timed out - Service slow or unreachable # (101) Network is unreachable - Network configuration issue ```
Common Causes
- 1.Backend not running: Upstream service is down
- 2.Wrong port: proxy_pass pointing to wrong port
- 3.Wrong host: Incorrect hostname or IP address
- 4.DNS resolution failure: Cannot resolve upstream hostname
- 5.Firewall blocking: Network rules preventing connection
- 6.Wrong protocol: HTTP vs HTTPS mismatch
- 7.SELinux blocking: Security policy preventing connection
- 8.Upstream server overload: Backend refusing new connections
- 9.Proxy headers missing: Upstream rejecting due to missing headers
- 10.Keepalive issues: Connection pooling problems
Step-by-Step Fix
- 1.Check logs for specific error messages
- 2.Verify configuration settings
- 3.Test network connectivity
- 4.Review recent changes
- 5.Apply corrective action
- 6.Verify the fix
Step 1: Verify Backend Server
Confirm the upstream is running:
```bash # Check if backend is running on expected port netstat -tulpn | grep :3000 ss -tulpn | grep :3000
# Check process ps aux | grep node ps aux | grep python systemctl status myapp
# Test direct connection to backend curl -I http://127.0.0.1:3000 curl -I http://localhost:3000 curl -I http://backend-server:8080
# Test with nc nc -zv 127.0.0.1 3000 telnet 127.0.0.1 3000
# For Docker/containerized backends docker ps docker logs backend-container ```
Step 2: Check Proxy Configuration
Verify proxy_pass settings:
# View current configuration
grep -r "proxy_pass" /etc/nginx/
nginx -T 2>/dev/null | grep -A 20 "proxy_pass"Correct proxy_pass syntax: ```nginx # Basic proxy location /api { proxy_pass http://127.0.0.1:3000; }
# With upstream block upstream backend { server 127.0.0.1:3000; }
location /api { proxy_pass http://backend; }
# With trailing slash (changes URI) location /api/ { proxy_pass http://127.0.0.1:3000/; # /api/users -> /users }
# Without trailing slash location /api/ { proxy_pass http://127.0.0.1:3000; # /api/users -> /api/users } ```
Step 3: Fix Wrong Port or Host
Correct upstream address:
```nginx # WRONG: Wrong port location /api { proxy_pass http://127.0.0.1:3000; # But app runs on 8080 }
# CORRECT: Match actual port location /api { proxy_pass http://127.0.0.1:8080; # Correct port }
# WRONG: Wrong hostname location /api { proxy_pass http://backend-server:3000; # Wrong hostname }
# CORRECT: Correct hostname location /api { proxy_pass http://app-server:3000; }
# For Docker services location /api { proxy_pass http://container-name:3000; # Or use Docker network name } ```
Step 4: Add Required Proxy Headers
Include necessary headers:
```nginx location /api { proxy_pass http://127.0.0.1:3000;
# Essential headers 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; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; }
# For WebSocket location /ws { proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }
# For HTTPS upstream location /api { proxy_pass https://api.example.com; proxy_ssl_server_name on; proxy_set_header Host api.example.com; } ```
Step 5: Fix DNS Resolution Issues
Handle DNS problems:
```nginx # Using resolver for dynamic upstreams location /api { resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s;
# Use variable to force DNS resolution set $upstream http://backend.example.com:3000; proxy_pass $upstream; }
# For Kubernetes services location /api { resolver kube-dns.kube-system.svc.cluster.local valid=5s; proxy_pass http://my-service.default.svc.cluster.local:3000; }
# For Docker Compose location /api { proxy_pass http://backend:3000; # Use service name } ```
Check DNS resolution: ```bash # Test DNS resolution nslookup backend.example.com dig backend.example.com
# Test from nginx server getent hosts backend.example.com
# Add to /etc/hosts if needed echo "192.168.1.100 backend.example.com" | sudo tee -a /etc/hosts ```
Step 6: Configure Timeouts
Set appropriate timeouts:
```nginx location /api { proxy_pass http://backend:3000;
# Connection timeout proxy_connect_timeout 60s;
# Read timeout (waiting for response) proxy_read_timeout 60s;
# Send timeout (sending request) proxy_send_timeout 60s;
# For long-running requests proxy_read_timeout 300s; }
# Upstream-level timeouts upstream backend { server 127.0.0.1:3000; keepalive 32; keepalive_timeout 60s; } ```
Step 7: Configure Connection Pooling
Enable keepalive connections:
```nginx upstream backend { server 127.0.0.1:3000; keepalive 32; # Keep 32 connections open keepalive_timeout 60s; keepalive_requests 1000; }
server { location /api { proxy_pass http://backend;
# Required for keepalive proxy_http_version 1.1; proxy_set_header Connection "";
# Don't close connections proxy_set_header Connection ""; } } ```
Step 8: Handle Firewall and SELinux
Allow network connections:
```bash # Check firewall rules sudo iptables -L -n sudo firewall-cmd --list-all
# Allow connections to backend sudo firewall-cmd --add-port=3000/tcp --permanent sudo firewall-cmd --reload
# For SELinux (CentOS/RHEL) getenforce # If Enforcing, allow HTTP network connections sudo setsebool -P httpd_can_network_connect 1 sudo setsebool -P httpd_can_network_relay 1
# Check SELinux denials sudo ausearch -m avc -ts recent | grep nginx
# Create SELinux policy if needed sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx-network sudo semodule -i nginx-network.pp ```
Step 9: Configure Buffer Settings
Handle large requests/responses:
```nginx location /api { proxy_pass http://backend:3000;
# Request body buffering proxy_request_buffering on; client_max_body_size 100m; client_body_buffer_size 1m;
# Response buffering proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 16k; proxy_busy_buffers_size 32k;
# For large responses proxy_buffers 8 32k; proxy_buffer_size 64k;
# For streaming (disable buffering) proxy_buffering off; proxy_request_buffering off; } ```
Step 10: Debug Proxy Issues
Enable detailed logging:
```nginx # Enable debug logging error_log /var/log/nginx/error.log debug;
# Log upstream address log_format proxy_log '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' 'upstream: $upstream_addr ' 'upstream_status: $upstream_status ' 'request_time: $request_time ' 'upstream_response_time: $upstream_response_time';
access_log /var/log/nginx/proxy.log proxy_log; ```
```bash # Watch proxy logs tail -f /var/log/nginx/error.log | grep -i upstream
# Test specific endpoint curl -v http://localhost/api/test
# Check upstream connectivity ss -tnp | grep nginx
# Monitor connections watch -n 1 'ss -tnp | grep nginx | wc -l' ```
Step 11: Test Upstream Directly
Bypass Nginx to isolate issue:
```bash # Test backend directly curl -v http://127.0.0.1:3000/api/test curl -v http://backend-server:8080/health
# Test with same headers Nginx sends curl -H "Host: localhost" \ -H "X-Real-IP: 127.0.0.1" \ http://127.0.0.1:3000/api/test
# Test specific endpoints for endpoint in /api/health /api/status /api/test; do echo "Testing $endpoint:" curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000$endpoint done
# Check if backend is listening on expected interface # May be listening on 127.0.0.1 but not 0.0.0.0 netstat -tulpn | grep 3000 ```
Step 12: Fix Common Upstream Issues
Address backend problems:
```bash # If backend not running, start it systemctl start myapp # Or for Node.js pm2 start app.js # Or for Python gunicorn app:app
# If wrong interface binding, reconfigure app # Change from 127.0.0.1 to 0.0.0.0 to accept all interfaces
# Check backend logs journalctl -u myapp -f tail -f /var/log/app/error.log
# For Docker docker logs -f backend-container docker inspect backend-container | grep IPAddress ```
Verification
Confirm proxy is working:
```bash # Test proxy endpoint curl -I http://localhost/api # Should return 200 OK
# Check error log for proxy errors tail -20 /var/log/nginx/error.log | grep -i "proxy|upstream" # Should not show connection errors
# Test multiple requests for i in {1..10}; do curl -s -o /dev/null -w "Request $i: %{http_code}\n" http://localhost/api done
# Verify proxy headers being sent curl -v http://localhost/api 2>&1 | grep -E "X-Forwarded|X-Real"
# Check upstream connectivity ss -tnp | grep :3000
# Monitor during load ab -n 100 -c 10 http://localhost/api/ ```
Proxy connections should now succeed and return proper responses from the upstream server.
Related Articles
- [Nginx troubleshooting: Fix Lambda Permission Denied - Complete ](fix-lambda-permission-denied)
- [Nginx web server troubleshooting: Fix Client Max Body Size Large Upload Nginx Issue ](client-max-body-size-large-upload-nginx)
- [Fix Apache 502 Proxy Error](fix-apache-502-proxy-error)
- [Fix Apache LogLevel Core Debug Configuration](fix-apache-loglevel-core-debug)
- [Fix Cloudflare 502 Bad Gateway Error](fix-cloudflare-502-bad-gateway)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Nginx Proxy Pass Not Working", "description": "Resolve Nginx proxy_pass connection refused errors with upstream configuration, DNS resolution, and proxy headers", "url": "https://www.fixwikihub.com/fix-nginx-proxy-connection-refused", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-19T21:38:02.168Z", "dateModified": "2025-11-19T21:38:02.168Z" } </script>