Ubuntu Nginx/Apache Log Guide: access/error Log Location and Analysis
What You'll Learn
- Where Nginx/Apache log files are located in Ubuntu
- How to isolate causes for "500/502/503/504", "403", "404" from logs
- A systematic approach to log investigation (order, filtering, reproduce, verify)
- Understanding that log bloat can cause disk issues
Quick Summary
When web is broken, follow this order:
- Check service status:
systemctl status nginx|apache2 - Check error log:
tail -n 200 .../error.log - Find failing request in access log:
grep " 500 " .../access.log - Reproduce and watch logs in real-time (most powerful)
- 502/503 means check upstream (app side)
Table of Contents
Prerequisites
- OS: Ubuntu
- Web Server: Nginx or Apache
sudoaccess- Fixed procedures for beginners to not get lost
1. Check Which Server Is Running (Nginx? Apache?)
Skip if you already know.
1-1. Check by Service Status
$ sudo systemctl status nginx $ sudo systemctl status apache2
nginxis active → Check Nginx logsapache2is active → Check Apache logs- Both active → Probably reverse proxy setup (check front-end logs first)
1-2. Check by Port (Supplemental)
$ sudo ss -lntp | grep ':80 ' $ sudo ss -lntp | grep ':443 '
2. Log Locations (Ubuntu Typical Paths)
Usually here on Ubuntu:
2-1. Nginx
- error log:
/var/log/nginx/error.log - access log:
/var/log/nginx/access.log
$ ls -la /var/log/nginx
2-2. Apache (apache2)
- error log:
/var/log/apache2/error.log - access log:
/var/log/apache2/access.log
$ ls -la /var/log/apache2
3. First Check "error log" (Fastest Path)
Access log shows "what happened", but root cause (stack trace/config error/upstream death) appears in error.log.
3-1. View Last 200 Lines (First Step)
# Nginx $ sudo tail -n 200 /var/log/nginx/error.log # Apache $ sudo tail -n 200 /var/log/apache2/error.log
3-2. Real-time Tracking While Reproducing (Most Powerful)
# Nginx $ sudo tail -f /var/log/nginx/error.log # Apache $ sudo tail -f /var/log/apache2/error.log
Keep this open, reproduce with browser/curl in another tab, and you'll find the cause fast. "Checked logs but couldn't understand" usually means not reproducing simultaneously.
4. Find Failing Request in access log
4-1. Find 500 Errors Only
$ sudo grep " 500 " /var/log/nginx/access.log | tail -n 50
4-2. Find 404 Errors Only
$ sudo grep " 404 " /var/log/nginx/access.log | tail -n 50
4-3. Find Specific Path Only (e.g., /api/)
$ sudo grep " /api/" /var/log/nginx/access.log | tail -n 50
5. Status Code Isolation Guide
5-1. 500 (Internal Server Error)
- App internal error (PHP/Node/Ruby, etc.)
- Config mistake (FastCGI settings, etc.)
- Permission/path (Permission denied) possible
Next: error.log (priority), app logs, journalctl -u
5-2. 502 / 503 / 504 (Bad Gateway / Service Unavailable / Gateway Timeout)
- Nginx/Apache can't connect to upstream / slow response / dead
Next step:
$ nc -vz 127.0.0.1 3000 $ curl -I http://127.0.0.1:3000
5-3. 403 (Forbidden)
- Basic auth, IP restriction, WAF, directory permission, file permission
Next: error.log will show "permission denied" or "client denied"
5-4. 404 (Not Found)
- Routing / file doesn't exist
- SPA rewrite config missing
6. Finding Non-Default Log Locations
6-1. Nginx: Dump All Config
$ sudo nginx -T 2>&1 | grep -E "access_log|error_log" | head -n 50
6-2. Apache: Check Config
$ sudo apache2ctl -S
7. Filtering Tips for Faster Investigation
7-1. Want to See Only What's Happening Now
Best: "reproduce → tail -f"
7-2. Filter by Keyword (e.g., upstream)
$ sudo grep -i "upstream" /var/log/nginx/error.log | tail -n 50
8. Common error.log Messages
8-1. connect() failed (111: Connection refused) while connecting to upstream
Meaning: Upstream isn't listening / down
$ nc -vz 127.0.0.1 <upstream-port> $ sudo systemctl status <app-service>
8-2. upstream timed out (110: Connection timed out)
Meaning: Upstream is slow/congested (load, DB, I/O, etc.)
8-3. permission denied
Meaning: File/directory permission issue, possibly SELinux/AppArmor
8-4. client intended to send too large body
Meaning: Upload size limit (nginx client_max_body_size, etc.)
9. Things to Avoid
Don't: Spam restart Without Checking Logs
Restarting without logs just hides the cause and wastes time. Check error.log / journalctl first.
Don't: Only Check access.log and Stop There
Root cause is usually in error.log. Access log is for "which request failed".
Don't: Ignore Log Bloat
More traffic = more logs. Can lead to disk full (No space left). Monitor disk and configure log rotation (logrotate).
Copy-Paste Template (Nginx Example)
# Service status sudo systemctl status nginx # Error (check this first) sudo tail -n 200 /var/log/nginx/error.log # Real-time tracking while reproducing (most powerful) sudo tail -f /var/log/nginx/error.log # Find failing requests sudo grep " 500 " /var/log/nginx/access.log | tail -n 50 sudo grep " 502 " /var/log/nginx/access.log | tail -n 50 sudo grep " 403 " /var/log/nginx/access.log | tail -n 50 sudo grep " 404 " /var/log/nginx/access.log | tail -n 50
Summary
- Check error.log first, then access.log
- Reproduce +
tail -fis the fastest path - 502/503/504 → investigate upstream (app). Use port connectivity checks.
- Logs consume disk. Can cause "No space left" issues.
Test Environment
Commands in this article were tested on Ubuntu 24.04 LTS / bash 5.2.