Skip to main content

Troubleshooting Matrix

Learning Focus

Leave this lesson with a working understanding of troubleshooting matrix that you can apply immediately in production.

Find your symptom, get the fix. Start with the diagnostic commands, then jump to the relevant section.


First Response — Always Run These

# 1. Config syntax OK?
sudo nginx -t

# 2. What's in the error log?
sudo tail -50 /var/log/nginx/error.log

# 3. Service running?
sudo systemctl status nginx

# 4. Ports listening?
sudo ss -tlnp | grep nginx

# 5. PHP-FPM OK?
sudo systemctl status php8.4-fpm
ls -la /run/php/php8.4-fpm.sock

# 6. Test response
curl -I http://localhost/
curl -H "Host: example.com" -I http://localhost/

502 Bad Gateway

Meaning: Nginx can't reach the backend (PHP-FPM or upstream app).

CauseError in LogFix
PHP-FPM not runningconnect() to ... failed: No such filesystemctl start php8.4-fpm
Wrong socket pathconnect() failed ... No such file or directoryls /run/php/ and fix path in nginx config
Socket permission deniedconnect() failed ... Permission deniedSet listen.owner = www-data in FPM pool config
Upstream app not runningconnect() to 127.0.0.1:3000 failedStart your Node.js/Python app
FPM out of workersupstream timed out under loadIncrease pm.max_children
# Diagnose 502 step by step
sudo tail -30 /var/log/nginx/error.log | grep "502\|upstream\|connect"

# Is PHP-FPM running?
sudo systemctl status php8.4-fpm

# Does the socket exist?
ls -la /run/php/php8.4-fpm.sock

# What socket path does Nginx expect?
sudo grep "fastcgi_pass" /etc/nginx/sites-enabled/*.conf

# Is the upstream app responding?
curl -I http://127.0.0.1:3000/

504 Gateway Timeout

Meaning: Backend responded too slowly — Nginx gave up waiting.

CauseFix
Slow PHP scriptIncrease fastcgi_read_timeout in Nginx config
Slow database queryCheck slow query log, add indexes
Upstream app slowIncrease proxy_read_timeout
PHP max_execution_time too lowIncrease in php.ini
# In location block — increase timeouts
fastcgi_read_timeout 300; # For PHP
proxy_read_timeout 300; # For upstream apps
proxy_connect_timeout 30;
# Check PHP execution time limit
php8.4 -r "echo ini_get('max_execution_time');"

# Watch what PHP is doing under load
sudo tail -f /var/log/php8.4-fpm-slow.log

403 Forbidden

CauseSymptomFix
Wrong file permissions403 on all pageschmod -R 755 /var/www/site/
Wrong ownership403 on all pageschown -R www-data:www-data /var/www/site/
No index file403 on /Create index.html or index.php in docroot
autoindex off + no index403 on directoryAdd index index.html index.php to server block
deny all rule403 on specific pathCheck location blocks for deny all
Hidden file blocked correctly403 on .envThis is correct — not a bug
# Fix permissions
sudo chown -R www-data:www-data /var/www/example.com/
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;

# Check what user Nginx runs as
ps aux | grep "nginx: worker" | head -2 | awk '{print $1}'

# Test if www-data can read the file
sudo -u www-data cat /var/www/example.com/public/index.php | head -3

404 Not Found

CauseFix
Wrong root pathCheck root in server block; verify directory exists
Site not enabledln -s sites-available/site sites-enabled/site and reload
Wrong server_nameVerify server_name matches the request hostname
Missing rewrite rulesAdd try_files $uri $uri/ /index.php?$args
alias vs root confusionalias = replaces location prefix; root = appends URI
# Verify root directory exists and has files
grep "root" /etc/nginx/sites-enabled/example.com.conf
ls -la /var/www/example.com/public/

# Check which server block handles the request
sudo nginx -T | grep -B5 "server_name.*example.com"

# Test with curl
curl -v http://localhost/404test 2>&1 | grep "< HTTP"

SSL / TLS Errors

Cloudflare 525 (SSL Handshake Failed)

# Cause: Nginx has no SSL listener or bad cert
# Check SSL listener
grep "ssl" /etc/nginx/sites-enabled/example.com.conf

# Verify cert and key files exist
ls -la /etc/ssl/certs/example.com.crt
ls -la /etc/ssl/private/example.com.key

# Verify cert is valid
openssl x509 -in /etc/ssl/certs/example.com.crt -noout -dates

# Verify key matches cert
openssl x509 -noout -modulus -in /etc/ssl/certs/example.com.crt | openssl md5
openssl rsa -noout -modulus -in /etc/ssl/private/example.com.key | openssl md5
# Both hashes must match

Cloudflare 526 (Invalid SSL Certificate)

# Cause: Self-signed cert but Cloudflare is in Full (Strict) mode
# Fix: Use Cloudflare Origin Certificate

openssl x509 -in /etc/ssl/certs/example.com.crt -noout -issuer
# If issuer is self-signed → replace with Cloudflare Origin Cert

ERR_SSL_PROTOCOL_ERROR

# Cause: Nginx not listening on 443 or bad SSL config
sudo ss -tlnp | grep :443
openssl s_client -connect example.com:443 -servername example.com

Nginx Won't Start

# Check config syntax
sudo nginx -t

# What's the exact error?
sudo nginx -t 2>&1

# Port already in use?
sudo ss -tlnp | grep ':80\|:443'
sudo lsof -i :80

# Common: Apache occupying port 80
sudo systemctl stop apache2
sudo systemctl start nginx

Config Change Not Taking Effect

# Did you actually reload?
sudo nginx -s reload

# Was there an error during reload? Check log
sudo tail -10 /var/log/nginx/error.log

# Verify the config file is included
sudo nginx -T | grep example.com

# Is the site enabled?
ls -la /etc/nginx/sites-enabled/ | grep example.com

Log Location Reference

LogPathWhat to Look For
Server errors/var/log/nginx/error.logAll errors — check first
Access log/var/log/nginx/access.logStatus codes, slow requests
Per-site error/var/log/nginx/example.com.error.logSite-specific errors
PHP-FPM/var/log/php8.4-fpm.logFPM pool errors
PHP slow log/var/log/php8.4-fpm-slow.logSlow PHP requests
PHP errorsValue of error_log in php.iniPHP-level errors