Logrotate#
Why#
Logs live on tmpfs (Filesystem chapter), in bounded RAM, without
rotation, a chatty service would eventually saturate its allocated quota.
logrotate handles this rotation, but two services in this project have
special needs beyond the generic case.
How#
nginx#
cat > /etc/logrotate.d/nginx <<'EOF'
/var/log/nginx/*.log {
daily
missingok
rotate 14
delaycompress
compress
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -HUP $(cat /var/run/nginx.pid)
endscript
}
EOFchrony#
cat > /etc/logrotate.d/chrony <<'EOF'
/var/log/chrony/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
postrotate
/usr/bin/chronyc cyclelogs > /dev/null 2>&1 || true
/usr/bin/chronyc trimlog > /dev/null 2>&1 || true
endscript
}
EOF
logrotate -d /etc/logrotate.d/nginx
logrotate -d /etc/logrotate.d/chronyrotate 14 keeps two weeks of compressed logs, a reasonable window given
/var/log’s tmpfs budget (256 MB, Filesystem chapter): these logs are
lost on every reboot anyway, so this rotation isn’t meant for long-term
archival, just a safety net between reboots. delaycompress delays
compressing the most recently rotated file by one cycle: the process in
question may need a brief moment after rotation to honor the postrotate
signal and stop writing to the old file descriptor, compressing
immediately would risk corrupting or losing the last few lines written
during that window.
Pitfalls to avoid#
Never create a
logrotate.d/auditconfiguration.auditdmanages its own internal rotation via themax_log_fileandnum_logsdirectives inauditd.conf. External rotation bylogrotateon top of auditd’s internal rotation would create double management of the same files, with a real risk of corrupting the audit daemon’s internal state (documented behavior inauditd.conf(8)). This is a deliberate exception, not an oversight.
- Forgetting nginx’s
postrotate. After rotation, nginx keeps writing to the old file (now renamed) until explicitly told to reopen its file descriptors, theSIGHUPsent to the master process does exactly that. Without it, new logs would silently keep going into the compressed/archived file. - Forgetting
chronyc cyclelogs. Chrony has the same need as nginx, reopening its log files after rotation, but through its own command rather than a generic Unix signal.
Verify#
# Dry-run simulation without actual execution (-d = debug)
logrotate -d /etc/logrotate.d/nginx
logrotate -d /etc/logrotate.d/chrony
# Force an actual rotation to test
logrotate -f /etc/logrotate.d/nginx
ls -la /var/log/nginx/
# Should show a fresh .log file and a .log.1.gz (or .log.1 before delayed compression)