Apache: what a chatterbox
Apache talks. A lot. Every request generates a line in the access_log, every error a line in the error_log and the LogLevel controls the chattiness. On a server serving 100,000 pages per day, the access_log weighs 50 MB per day and nobody reads it.
The LogLevel
LogLevel warn
The levels, from chattiest to quietest: debug, info, notice, warn, error, crit, alert, emerg. warn is the default and the right one: it logs warnings (config, permissions) and errors, but not every module starting up.
debug is useful during a debugging session, but it produces 50 lines per request (every module, every rewrite rule, every header processed). In production, debug is a disk drive filling up.
The LogFormat
The combined default adds User-Agent and Referer to the classic:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/log/apache2/access.log combined
What the access_log tells: source IP, timestamp, method + URL + protocol, return code, size, Referer (where the user came from) and User-Agent (which browser, which OS, which bot). An access_log is a behavioral database and nobody treats it as such.
What you find in it
- Scanner bots:
/phpmyadmin,/wp-admin,/etc/passwd,/shell.php(the IPs that fail2ban bans) - Spam referers (domains claiming to link to you to appear in your stats)
- Scanner User-Agents (sqlmap, nikto, sqlninja) that distinguish from browsers by their pattern
- Requests that do not get a 200: 404s on files that do not exist, 403s on protected files, 500s on application errors
The rotation
CustomLog "|/usr/bin/rotatelogs /var/log/apache2/access.log 86400" combined
Apache’s rotatelogs rotates the log every 86400 seconds (24h) without stopping Apache. Compression and cleanup are in logrotate:
/var/log/apache2/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
}
14 days of compressed logs, the first two days uncompressed (delaycompress, for the ongoing tail).
[edit: 2026] The combined LogFormat is still the standard, but modern access logs are parsed by pipelines (GoAccess in realtime, ELK for aggregation, fail2ban for banning). User-Agent is now the most lying field: bots have been impersonating Chrome since 2020 and Referer is empty for HTTPS-to-HTTP transitions. The log still tells everything, but you have to read between the lines.