nginx errors — most often config syntax (nginx -t catches), permissions (error.log), upstream issues (502/504). Debug steps: tail error.log, curl test from different angles, strace on process. Top 5 errors: 502 Bad Gateway (upstream down), 504 Gateway Timeout (slow upstream), 403 Forbidden (permissions), 400 Bad Request (header size), worker process crashes.
Below: step-by-step, working examples, common pitfalls, FAQ.
nginx -t — catches syntax errors before reloadtail -f /var/log/nginx/error.logtail -f /var/log/nginx/access.logerror_log /var/log/nginx/error.log debug; in nginx.confcurl -I http://127.0.0.1:3000/ (skip nginx)ls -la /var/www/site/ — nginx user must be able to readaudit2allow -a, aa-statussystemctl reload nginx (SIGHUP, no downtime)| Scenario | Config |
|---|---|
| Config test | nginx -t
# Ok:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# Errors:
nginx: [emerg] unknown directive "incude" in /etc/nginx/nginx.conf:5 |
| 502 Bad Gateway debug | # error.log:
# 2026/04/18 upstream connect() failed (111: Connection refused) while connecting to upstream, client: 1.2.3.4, server: example.com, upstream: "http://127.0.0.1:3000/"
# Fix: app on 127.0.0.1:3000 is down. Check:
systemctl status myapp
ss -tlnp | grep 3000 |
| 504 Gateway Timeout | # Increase timeouts
location /api/ {
proxy_pass http://backend;
proxy_read_timeout 60s; # default 60s
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
} |
| 413 Entity Too Large | # nginx.conf http {
client_max_body_size 100m;
}
# For file uploads — increase. Default 1M is too small |
| Permission debug | sudo -u www-data cat /var/www/site/index.html # check if user has access
ls -la /var/www/site/ # owner must read
chown -R www-data:www-data /var/www/site
chmod -R 755 /var/www/site
find /var/www/site -type f -exec chmod 644 {} \; |
nginx -t firstproxy_pass http://backend; (no /) vs proxy_pass http://backend/; (with /)chcon -R -t httpd_sys_content_t /var/www<code>events { debug_connection 1.2.3.4; }</code> in nginx.conf — debug only for this client.
Configure <code>set_real_ip_from 10.0.0.0/8;</code> + <code>real_ip_header X-Forwarded-For;</code> — nginx will show client IP instead of proxy.
<code>nginx_upstream_check_module</code> (patch for OSS nginx). Or plain passive health checks via <code>max_fails=3 fail_timeout=30s</code>.
<code>tcpdump</code> on server → capture traffic, analyze in Wireshark. Or DevTools Network tab for client-side.