If you run a website on Apache, sooner or later something is going to break. A plugin will throw a fatal error, a permissions issue will block a script from running, or a misconfigured virtual host will start returning 500 errors out of nowhere. When that happens, the first place I go is the Apache error log. I’ve been managing Apache servers for years now, and I can tell you that a well-configured error log has saved me more debugging time than almost any other tool in my sysadmin toolkit.
What Is the Apache Error Log and Why Does It Matter
The Apache error log is where the web server writes down everything that goes wrong (and a lot of things that go right, depending on your log level). This includes server startup and shutdown messages, module loading issues, PHP or CGI errors, permission denials, and any warnings the server generates while processing requests.
Unlike the access log, which just records who requested what and when, the error log tells you why something failed. If I had to pick one log file to keep an eye on when a site goes down, it would always be this one.
Prerequisites
Before diving in, here’s what I assume you already have in place:
- A Linux server (I’ll use Ubuntu/Debian and CentOS/RHEL examples) with Apache (httpd) installed
- Root or sudo access to the server
- Basic familiarity with the command line and a text editor like
nanoorvim - Apache installed via
apt(Debian/Ubuntu) oryum/dnf(CentOS/RHEL/Fedora)
If you haven’t installed Apache yet, a quick sudo apt install apache2 (Debian-based) or sudo dnf install httpd (RHEL-based) will get you there.
Where Apache Error Logs Live by Default
The default location depends on your distribution:
- Debian/Ubuntu:
/var/log/apache2/error.log - CentOS/RHEL/Fedora:
/var/log/httpd/error_log
You can always confirm the active path by checking your main configuration file:
# Debian/Ubuntu
grep -r "ErrorLog" /etc/apache2/
# CentOS/RHEL
grep -r "ErrorLog" /etc/httpd/
Basic Error Log Configuration
The core directive you need is ErrorLog. It’s usually set in the main config file (apache2.conf or httpd.conf) and can be overridden per virtual host.
ErrorLog ${APACHE_LOG_DIR}/error.log
On CentOS, you’ll see something closer to:
ErrorLog "logs/error_log"
I always recommend keeping this directive explicit rather than relying purely on defaults, especially once you start managing multiple sites on one server.
Setting the Log Level
Apache lets you control how verbose the error log is with the LogLevel directive. The levels, from least to most verbose, are:
emerg -> alert -> crit -> error -> warn -> notice -> info -> debug -> trace1-8
In production, I stick with warn most of the time:
LogLevel warn
When I’m actively debugging something, I’ll temporarily bump it up:
LogLevel debug
Just remember to set it back afterward — debug and trace levels generate a lot of noise and can bloat your logs fast.
Module-Specific Log Levels
One trick I use often is setting a different log level for a specific module. For example, if I only want verbose logging from mod_rewrite while troubleshooting redirect rules:
LogLevel warn rewrite:trace3
This keeps the rest of the server quiet while giving me detailed rewrite debugging.
Per-Virtual-Host Error Logs
If you’re hosting multiple sites on one server (which is almost always the case for me), you’ll want a separate error log per virtual host. This makes troubleshooting dramatically easier because you’re not sifting through unrelated traffic from other domains.
Here’s a typical virtual host block:
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/example.com/public_html
ErrorLog /var/log/apache2/example.com-error.log
LogLevel warn
CustomLog /var/log/apache2/example.com-access.log combined
</VirtualHost>
I do this for every domain I host. It takes an extra thirty seconds per site and pays off enormously the first time something breaks.
Reloading Apache After Changes
Any time you edit the config, you need to test and reload:
# Test configuration syntax
sudo apachectl configtest
# or
sudo apache2ctl configtest
# Reload gracefully (no dropped connections)
sudo systemctl reload apache2 # Debian/Ubuntu
sudo systemctl reload httpd # CentOS/RHEL
I never skip the configtest step. A typo in your ErrorLog path can prevent Apache from starting entirely, and that’s a bad way to find out you made a mistake.
Reading and Filtering the Error Log
Once logging is set up, here’s how I actually use it day to day.
Tailing in Real Time
sudo tail -f /var/log/apache2/error.log
I keep this running in a terminal tab whenever I’m deploying changes or testing a new feature.
Searching for Specific Errors
grep -i "permission denied" /var/log/apache2/error.log
grep -i "php fatal" /var/log/apache2/error.log
Counting Error Frequency
awk '{print $9}' /var/log/apache2/error.log | sort | uniq -c | sort -nr
This kind of quick frequency count is often how I spot a recurring issue before it becomes a major outage.
Log Rotation
Left unmanaged, error logs will grow forever and eventually fill your disk. Both major distros ship with logrotate pre-configured for Apache, but it’s worth checking the config:
cat /etc/logrotate.d/apache2 # Debian/Ubuntu
cat /etc/logrotate.d/httpd # CentOS/RHEL
A typical rotation config looks like this:
/var/log/apache2/*.log {
weekly
missingok
rotate 14
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
systemctl reload apache2 > /dev/null
endscript
}
I usually adjust rotate to keep 30 days of logs instead of 14, since I’ve needed to go back further than two weeks more than once while investigating an intermittent bug.
Real-World Use Cases
Here are a few scenarios where the error log has directly saved me:
- 500 Internal Server Errors: The error log almost always tells you exactly which PHP file and line number triggered the failure.
- .htaccess issues: Misconfigured rewrite rules or syntax errors in
.htaccessshow up here immediately. - Permission problems: “Permission denied” errors for file access are logged clearly, saving hours of guesswork.
- Module conflicts: When two modules fight over the same functionality, Apache usually logs a warning at startup.
- SSL certificate issues: Expired or misconfigured certificates generate specific, readable error messages.
Troubleshooting Tips
- If the error log isn’t updating at all, check that Apache actually has write permission to the log directory (
ls -l /var/log/apache2/). - If you see “AH00526” errors, that’s Apache telling you there’s a syntax error in a specific config file and line — always read the full message, it names the exact file.
- On SELinux-enabled systems (common on CentOS/RHEL), a correctly configured
ErrorLogpath can still fail silently if SELinux context is wrong. Runrestorecon -v /var/log/httpd/if logs mysteriously stop. - If logs seem to disappear after rotation, check that your
postrotatescript is actually reloading Apache — otherwise Apache keeps writing to the old (now renamed) file handle.
Common Mistakes to Avoid
- Leaving
LogLevel debugon in production. It fills disks fast and can leak sensitive info into logs. - Sharing one error log across all virtual hosts. This makes debugging a specific site painful.
- Forgetting to run
configtestbefore reloading. A badErrorLogpath can stop Apache from starting. - Not rotating logs at all. I’ve seen a
/varpartition fill up completely because of this. - Ignoring warnings. A
warn-level message today is often anerror-level outage tomorrow.
Security Best Practices
- Restrict log file permissions so only root and the
admgroup (or equivalent) can read them — logs can contain sensitive path or query data. - Avoid logging at
debug/tracelevels long-term, since verbose logs can capture things like session tokens in edge cases. - Store logs outside the web root so they’re never directly accessible over HTTP.
- If you’re centralizing logs (e.g., shipping to a SIEM or log aggregator), use TLS for transport.
Performance Optimization
- Use
BufferedLogs Oncautiously — it can reduce disk I/O for high-traffic servers, though it slightly delays log writes. - Keep
LogLevelatwarnorerrorin production; verbose logging adds measurable I/O overhead on busy servers. - Rotate and compress logs regularly so log-related disk I/O doesn’t compete with your application.
Frequently Asked Questions
Q: Where is the Apache error log located by default? A: On Debian/Ubuntu it’s /var/log/apache2/error.log; on CentOS/RHEL it’s /var/log/httpd/error_log.
Q: How do I change the error log location? A: Edit the ErrorLog directive in your main config or virtual host block, then run apachectl configtest and reload Apache.
Q: What’s the difference between the error log and access log? A: The access log records every request (who, what, when, response code). The error log records problems — warnings, failures, and diagnostic messages.
Q: How do I stop my error log from growing too large? A: Set up logrotate (usually already configured) and keep LogLevel at a reasonable level like warn instead of debug.
Q: Can I have different log levels for different modules? A: Yes — use syntax like LogLevel warn rewrite:trace3 to set a module-specific level alongside your global level.
Summary and Key Takeaways
Setting up Apache error logs properly is one of those unglamorous tasks that pays off every single time something breaks. To recap what I covered:
- The
ErrorLogdirective controls where errors are written;LogLevelcontrols how much detail you get. - Set up per-virtual-host error logs when running multiple sites.
- Always run
configtestbefore reloading Apache after config changes. - Configure log rotation so logs don’t fill your disk.
- Keep production log levels reasonable, and only bump up verbosity temporarily while debugging.
A little discipline here means that when something does go wrong — and it will — you’ll have exactly the information you need to fix it fast.