High-traffic Apache servers can generate large access and error logs, and unattended growth can exhaust disk space, trigger outages, and bury incident evidence under noise.
On most Linux systems, logrotate rotates logs by renaming files on a schedule or size threshold, optionally compressing older copies to save space. Apache keeps log file descriptors open, so rotation is typically paired with a reload or graceful restart to reopen log files and continue writing to the current paths.
The examples assume file-based logging under /var/log/apache2 on Debian-style systems using /etc/logrotate.d/apache2; custom per-virtual-host paths must be included in rotation patterns to avoid unbounded growth. Avoid copytruncate for busy servers because it can drop or duplicate lines under load, and avoid double-rotation when logs are already piped through rotatelogs.
Steps to configure log rotation for Apache:
- List ErrorLog, CustomLog directives to confirm the active log paths.
$ sudo grep --recursive --line-number --extended-regexp '^[[:space:]]*(ErrorLog|CustomLog)[[:space:]]' /etc/apache2/ 2>/dev/null | head -n 12 /etc/apache2/apache2.conf:ErrorLog ${APACHE_LOG_DIR}/error.log /etc/apache2/sites-enabled/000-default.conf:CustomLog ${APACHE_LOG_DIR}/access.log combined ##### snipped ##### - Resolve the Debian-style ${APACHE_LOG_DIR} value used in the configuration.
$ sudo bash -c 'source /etc/apache2/envvars && echo "$APACHE_LOG_DIR"' /var/log/apache2
RHEL-style systems commonly use /var/log/httpd with /etc/logrotate.d/httpd.
- Record current log sizes to establish a baseline before changing rotation.
$ sudo ls -lh /var/log/apache2/ | head -n 20 total 28M -rw-r----- 1 root adm 22M Dec 13 09:05 access.log -rw-r----- 1 root adm 5.4M Dec 13 09:05 error.log ##### snipped #####
- Locate the logrotate policy file that applies to Apache.
$ sudo ls -la /etc/logrotate.d/apache2 -rw-r--r-- 1 root root 378 Aug 8 12:11 /etc/logrotate.d/apache2
- Review the current rotation settings for log patterns, including the postrotate signal.
$ sudo sed -n '1,200p' /etc/logrotate.d/apache2 /var/log/apache2/*.log { daily rotate 14 compress delaycompress missingok notifempty sharedscripts postrotate /usr/sbin/apachectl graceful >/dev/null 2>&1 || true endscript }A missing reopen signal leaves Apache writing to the renamed file, which defeats rotation.
- Update the rotation policy to match retention and permissions requirements.
/var/log/apache2/*.log { daily rotate 14 compress delaycompress missingok notifempty create 640 root adm sharedscripts postrotate /usr/sbin/apachectl graceful >/dev/null 2>&1 || true endscript }Add size 100M to rotate by size, or replace daily with weekly for slower-growing logs.
Add su root adm if logrotate refuses to rotate due to directory permission safety checks.
- Add a separate logrotate stanza for any logs written outside /var/log/apache2.
/srv/www/*/logs/*.log { weekly rotate 8 compress delaycompress missingok notifempty create 640 root adm sharedscripts postrotate /usr/sbin/apachectl graceful >/dev/null 2>&1 || true endscript }Keep rotation patterns tight to avoid rotating non-Apache logs with incompatible ownership or reopen behavior.
- Run a dry run to validate the policy without changing files.
$ sudo logrotate --debug /etc/logrotate.d/apache2 reading config file /etc/logrotate.d/apache2 rotating pattern: /var/log/apache2/*.log after 1 days (14 rotations) considering log /var/log/apache2/access.log log needs rotating considering log /var/log/apache2/error.log log needs rotating ##### snipped #####
- Force a rotation to validate behavior in a controlled window.
$ sudo logrotate --force /etc/logrotate.d/apache2
Forced rotation renames files immediately, which can add I/O load and complicate troubleshooting if log names change mid-incident.
- Confirm rotated logs exist with a fresh replacement file.
$ sudo ls -lh /var/log/apache2/ | grep --extended-regexp 'access\.log|error\.log' -rw-r----- 1 root adm 12K Dec 13 09:06 access.log -rw-r----- 1 root adm 22M Dec 13 09:05 access.log.1 -rw-r----- 1 root adm 6.0K Dec 13 09:06 error.log -rw-r----- 1 root adm 5.4M Dec 13 09:05 error.log.1
- Verify that Apache remains active after rotation.
$ sudo systemctl status apache2 --no-pager --lines=12 ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled) Active: active (running) since Sat 2025-12-13 09:06:02 UTC; 8s ago ##### snipped ##### - Generate a local request to create a new access-log entry.
$ curl --head --silent --output /dev/null --write-out '%{http_code}\n' http://localhost/ 200Any request that reaches Apache (browser refresh, health check, load balancer probe) can be used for this verification.
- Confirm the active access log receives fresh entries after rotation.
$ sudo tail -n 3 /var/log/apache2/access.log 127.0.0.1 - - [13/Dec/2025:09:06:18 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.88.1" ##### snipped #####
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
