← Back to Apache Course | Chapter 6: Logging | Lesson 4 of 4

Log Rotation

Log files grow forever unless something manages them -- log rotation periodically compresses old logs, deletes ones past a certain age, and starts Apache writing to a fresh file, so logs don't quietly fill up the disk.

logrotate

On Linux, the standard tool is logrotate, a general-purpose utility (not specific to Apache) that most distros already run daily via cron/systemd timer. Apache's package typically installs a ready-made config at /etc/logrotate.d/apache2 (or httpd) that rotates its default logs automatically -- no setup required for the defaults, though custom per-site log paths need to be added to it manually.

A logrotate Config

A typical block specifies the log file's path, daily/weekly for how often to rotate, rotate 14 for how many old copies to keep, compress to gzip old copies, and missingok/notifempty to avoid errors if the file doesn't exist yet or has nothing new in it.

Telling Apache About the New File

Simply renaming the log file isn't enough -- Apache keeps the original file handle open and would keep writing to the now-renamed (about to be compressed) file forever. A postrotate script that runs systemctl reload apache2 (or sends Apache a graceful restart signal) tells it to reopen its log files fresh after rotation.

Warning: Forgetting the postrotate reload step means Apache keeps writing to the renamed/compressed old file by its file handle, so the new log file stays empty while disk usage doesn't actually improve.

How Much History to Keep

How long to retain logs depends on the site's needs -- debugging a recent issue usually only needs a couple of weeks, but compliance or security requirements sometimes mandate months of retention. Compressed logs take a fraction of the space of raw ones, which makes keeping a longer history much cheaper than it first appears.

Example: A logrotate config for a custom per-site log

apacheconf
/var/log/apache2/example.com-*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    postrotate
        systemctl reload apache2 > /dev/null 2>/dev/null || true
    endscript
}
{# Flagged by hand after confirming a runner can't handle this example (a shell command / go.mod file stored as a TopicExample, a language feature the configured runner version doesn't support, or output that blows a runner's sandbox limit) -- see TopicExample.norun. Never render the run button for these, regardless of language, since it would just fail at execute_code (or worse, hang the Judge0 queue on a submission that can never finish cleanly). #}

⚠️ This example can't run in the browser editor. Try it in your own local environment instead.

{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Adding a custom per-VirtualHost log path without also adding it to logrotate's configuration, so it grows unbounded while the default logs rotate fine.
  2. Forgetting the postrotate reload, leaving Apache writing to a file that's already been renamed and compressed.
  3. Setting retention far higher than actually needed "just in case," using up disk space that later causes an unrelated outage when the disk fills.
Chapter Summary
  • The access log records every request (who, what, when, response code); the error log records what went wrong (startup failures, permission errors, PHP fatals) -- together they're the first place to look for almost any Apache problem.
  • LogFormat lets you customize exactly what's captured (like response time with %D), and logrotate keeps logs from growing forever -- but only if custom log paths are added to it and Apache is reloaded after each rotation.
🔒

Chapter Quiz — Complete all 4 topics to unlock

0/4 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.