गाइड · होस्टिंग और CDN

Apache vs nginx Troubleshooting: Logs, Config Tests and Common Errors

Side-by-side troubleshooting for Apache and nginx: where logs live, config test commands, restart vs reload, and fixes for the most common startup and runtime errors.

लेखक: SiteDownCheck संपादकीय टीम · अपडेट: अक्टूबर 5, 2026 · 8 मिनट पढ़ने में

Apache and nginx fail in similar ways but name things differently, and an administrator who knows one often loses time on the other. When a site is down, you need the same four answers fast: is the server running, is it listening, what does the config say, and what does the error log say. This guide puts the commands for both servers side by side, then covers the most common errors and the difference between restarting and reloading.

Paths below follow typical packages. Debian and Ubuntu use apache2, while RHEL, Rocky, AlmaLinux and Fedora use httpd. Always confirm on your own system.

The four-question checklist

  1. Is the process running?
  2. Is it listening on the expected ports?
  3. Does the configuration pass its syntax test?
  4. What does the error log say?

1. Is it running?

# nginx
sudo systemctl status nginx --no-pager
# Apache (Debian/Ubuntu)
sudo systemctl status apache2 --no-pager
# Apache (RHEL family)
sudo systemctl status httpd --no-pager

# If the service failed to start, the journal usually has the reason
sudo journalctl -u nginx -n 50 --no-pager
sudo journalctl -u apache2 -n 50 --no-pager

2. Is it listening?

sudo ss -ltnp | grep -E ':(80|443)\b'

You should see nginx, apache2, or httpd in the process column. If another program owns the port, you have a conflict (see "Address already in use" below). From outside the server, use the पोर्ट चेकर to see whether ports 80 and 443 are reachable through your firewall.

3. Does the config pass its test?

TasknginxApache
Syntax testsudo nginx -tsudo apachectl configtest or sudo apache2ctl -t or sudo httpd -t
Dump full effective configsudo nginx -Tsudo apachectl -S (virtual hosts), -M (modules), httpd -t -D DUMP_INCLUDES
Show version and build optionsnginx -Vapachectl -V
List loaded modules`nginx -V 2>&1 \grep -o 'with-[a-z_]*'`apachectl -M

Always test before applying changes. nginx -t reports the file and line of an error. Apache's configtest prints Syntax OK when it passes.

apachectl -S is especially valuable. It shows which virtual host answers for each name and port, plus the main config file locations. A surprising number of "wrong site shows up" problems are visible there:

sudo apachectl -S
sudo nginx -T | grep -E "server_name|listen"

4. What does the log say?

LognginxApache (Debian)Apache (RHEL)
Error log/var/log/nginx/error.log/var/log/apache2/error.log/var/log/httpd/error_log
Access log/var/log/nginx/access.log/var/log/apache2/access.log/var/log/httpd/access_log

Per-site logs are common, so check the ErrorLog and CustomLog directives (Apache) or error_log and access_log directives (nginx) in the vhost.

sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/apache2/error.log

# Top status codes in the last 10,000 requests (default combined format)
sudo tail -n 10000 /var/log/nginx/access.log | awk '{print $9}' | sort | uniq -c | sort -rn

The HTTP स्टेटस चेकर shows the code as the outside world sees it, which you can compare with the log.

Restart vs reload

ActionnginxApacheEffect
Reloadsudo systemctl reload nginxsudo systemctl reload apache2Re-reads config, workers finish current requests gracefully
Restartsudo systemctl restart nginxsudo systemctl restart apache2Stops and starts the service, dropping active connections

Use reload for configuration changes. It is the graceful option: nginx starts new workers with the new config and lets old workers finish, and Apache's graceful reload does the equivalent. If the new config has a syntax error, a reload leaves the old config running, which is why you test first.

Use restart when:

  • Loading or unloading a module that reload does not handle.
  • Changing something that requires a full process restart, such as listening addresses or ports in some setups.
  • The process is wedged and not responding.
  • You've changed the user or the main-process-level limits.

A habit worth building:

sudo nginx -t && sudo systemctl reload nginx
sudo apachectl configtest && sudo systemctl reload apache2

Common startup errors

Address already in use

nginx: bind() to 0.0.0.0:80 failed (98: Address already in use) Apache: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:80

Another process holds the port, often the other web server, or an old instance.

sudo ss -ltnp | grep ':80\b'

Stop the conflicting service or change the listen port. Installing both Apache and nginx on one box without changing ports is a classic cause.

Unknown directive or invalid command

nginx: unknown directive "xyz" in /etc/nginx/sites-enabled/site:12 Apache: Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration

A typo, or a missing module. For Apache, enable it:

sudo a2enmod rewrite headers ssl proxy_fcgi
sudo systemctl restart apache2

In nginx, some directives need modules compiled in. Check nginx -V.

Certificate or key problems

nginx: cannot load certificate "...": BIO_new_file() failed or key values mismatch Apache: AH02562: Failed to configure certificate

Check the paths, permissions, and that the certificate and private key belong together. A mismatch means one was replaced without the other. Test with the SSL Checker once running, and read SSL/TLS certificate errors explained.

openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa  -noout -modulus -in key.pem  | openssl md5

The two hashes must match for RSA keys.

Common runtime errors

403 Forbidden

  • nginx: directory index of "/var/www/site/" is forbidden means no index file and autoindex is off. open() "..." failed (13: Permission denied) means the nginx user cannot read the path, including every parent directory.
  • Apache: AH01630: client denied by server configuration or AH01276: Cannot serve directory ...: No matching DirectoryIndex. Check the <Directory> block has Require all granted and the right DirectoryIndex.

Check filesystem access as the web user:

sudo -u www-data stat /var/www/site/index.html
namei -l /var/www/site/index.html

namei -l reveals which parent directory lacks the execute bit.

404 where the file exists

  • Wrong root (nginx) or DocumentRoot (Apache), or the wrong vhost answering. Check which block matched with apachectl -S or by adding a temporary add_header X-Debug $server_name; in nginx.
  • Missing rewrite rules for a framework or CMS: nginx needs try_files $uri $uri/ /index.php?$args;, and Apache needs AllowOverride All for .htaccess rules to work, along with mod_rewrite enabled.

500 Internal Server Error

  • Apache: a bad .htaccess is the top cause, shown in the error log as .htaccess: Invalid command or RewriteRule: bad flag delimiters. Rename it temporarily to confirm.
  • nginx: a 500 comes from a rewrite loop (rewrite or internal redirection cycle) or from the upstream. See fix 500 internal server error.

502 and 504

These come from proxying and are covered in nginx 502 and 504 timeout tuning और fix 502 bad gateway. On Apache, the equivalent log messages include AH01114: HTTP: failed to make connection to backend and AH00957, and the timeout is ProxyTimeout (or Timeout as the default fallback).

503 and worker exhaustion

Apache logs AH00161: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting. All workers are busy, and new requests wait or fail. Check your MPM and limits:

apachectl -V | grep -i mpm
sudo apachectl -M | grep mpm

Raising MaxRequestWorkers without enough RAM leads to swapping or out-of-memory kills. Compute it from memory per worker. With the event MPM and PHP-FPM, memory per request is much lower than with prefork and mod_php. nginx uses worker_processes auto; and worker_connections rather than a worker-per-request model, and logs worker_connections are not enough when exhausted. See fix 503 service unavailable.

Configuration differences that trip people up

TopicnginxApache
Per-directory overridesNot supported; edit config and reload.htaccess (needs AllowOverride)
Enable a siteSymlink into sites-enabled (Debian) and reloada2ensite site.conf and reload
Request matchingserver_name plus location blocks, with specific matching rules for order<VirtualHost> and <Directory>/<Location> merged in a defined order
PHPAlways via FastCGI (PHP-FPM)mod_php or PHP-FPM through proxy_fcgi
Config changes take effectOn reloadOn reload (and .htaccess changes take effect immediately)

The .htaccess row explains many "my change did nothing" reports: moving a site from Apache to nginx means translating rewrite rules into nginx config, since nginx ignores .htaccess entirely.

When the server is fine but the site is down

Don't assume the web server is at fault. Work outward:

  1. curl -I http://127.0.0.1/ -H "Host: example.com" on the server confirms the web server answers locally.
  2. If it does, test from outside with the HTTP Header Checker to find firewall, DNS, or CDN issues.
  3. Verify DNS and the certificate. See why is my website down.
  4. Check the disk: df -h and df -i. A full disk stops logging and can crash services.
curl -sI http://127.0.0.1/ -H "Host: example.com"
df -h; df -i
free -m

अगले कदम

सामान्य प्रश्न

Should I restart or reload after editing the config?

Reload, after a successful syntax test. Reload applies changes without dropping active connections, and keeps the old config if the new one fails to load.

Why does my .htaccess do nothing on nginx?

nginx does not read .htaccess files. Translate the rules into nginx location and rewrite or try_files directives in the server config.

How do I find which virtual host is answering?

On Apache, run apachectl -S. On nginx, run nginx -T and search for server_name and listen, or add a temporary response header showing $server_name.

Where are the logs if I don't see them in /var/log?

They may be configured per site or sent to the journal. Run nginx -T or apachectl -S, look for error_log or ErrorLog directives, and check journalctl -u <service>.

Get notified when this guide updates

Plus occasional practical tips on uptime and monitoring, nothing else. Unsubscribe anytime.

यह पेज सामान्य जानकारी है, जिसे हमारी संपादकीय टीम ने लिखा है और दस्तावेज़ीकरण बदलने पर अपडेट किया जाता है। सर्वर और प्रदाता अलग-अलग होते हैं, इसलिए बदलाव पहले सुरक्षित तरीके से जाँचें। देखें: संपादकीय नीति और अस्वीकरण.