--
Logrotate
Overview
logrotate is a system utility that rotates, compresses, and prunes log files based on rules (size, age, count). It prevents logs from consuming disk space while keeping a retention window for troubleshooting and auditing. On most Linux distributions it is run automatically via cron or systemd timers, applying policies from /etc/logrotate.conf and /etc/logrotate.d/.
History
- As Unix/Linux systems standardized on file-based logging, log rotation emerged to keep long-running servers stable by controlling log growth.
logrotatebecame the common Linux solution by supporting flexible policies, post-rotate actions, and integration with service reload signals.
Adoption
logrotate is commonly used in:
- Traditional Linux servers using file-based logs (syslog, application logs, web server logs)
- VPS and bare-metal deployments where disk space must be managed locally
- Container hosts and K8s nodes where host logs still need rotation (even if apps use structured logging elsewhere)
Maintainer
Maintained by the Linux distribution and logrotate project/community (packaged and patched by distros).
Best when to use
- Logs are written to files and you need predictable retention and disk usage control
- You need compressed historical logs for a defined period
- You must run post-rotation actions (signal a daemon, reload a service, run scripts)
Not suitable when
- Logs are exclusively shipped to centralized storage and local files are not used
- Your application uses log output only to stdout/stderr inside containers with no file logs
- You need real-time streaming log management rather than periodic rotation
Compatibility notes
-
Rotation scheduling differs:
- Cron-based systems commonly run daily via
/etc/cron.daily/logrotate. - Systemd-based systems often use
logrotate.timer.
- Cron-based systems commonly run daily via
-
Service integration differs: some daemons support
copytruncate, others require a signal or reload after rotation. -
Journald logs are not rotated by
logrotate; they are managed byjournalctland journald settings.
Using copytruncate can lose log lines under heavy write load. Prefer a proper reopen mechanism (signal/reload) when the application supports it.
How it works
logrotate applies rules to a set of log files:
- Decide if a log needs rotation (time-based or size-based)
- Rename the current log (for example,
app.log→app.log.1) - Optionally compress rotated logs
- Create a fresh log file with the correct owner/permissions (if configured)
- Run post-rotation actions (signal/reload services)
- Delete logs beyond retention
Installation
Verify (read-only)
logrotate --version
Install
- Debian/Ubuntu
- Fedora/RHEL family
- Arch
sudo apt update
sudo apt install logrotate
sudo dnf install logrotate
sudo pacman -S logrotate
Configuration locations
| Location | Purpose |
|---|---|
/etc/logrotate.conf | Global defaults and includes |
/etc/logrotate.d/ | Per-service rotation rules |
/var/lib/logrotate/status | Rotation state tracking (last run timestamps) |
View current global config (read-only):
sudo sed -n '1,200p' /etc/logrotate.conf
List per-service rules:
sudo ls -la /etc/logrotate.d/
Common directives
| Directive | Meaning | Example |
|---|---|---|
| - | -- | |
daily / weekly / monthly | Rotate by time | weekly |
size | Rotate when log exceeds size | size 100M |
rotate N | Keep N rotations | rotate 14 |
compress | Compress rotated logs | compress |
delaycompress | Compress from the second rotation onward | delaycompress |
missingok | Skip if log missing | missingok |
notifempty | Don’t rotate empty logs | notifempty |
create MODE OWNER GROUP | Create new log with perms | create 0640 www-data adm |
su USER GROUP | Rotate using that user/group | su root adm |
dateext | Append date to rotated files | dateext |
dateformat | Customize date suffix | dateformat -%Y%m%d |
copytruncate | Copy then truncate original | copytruncate |
sharedscripts | Run scripts once per block | sharedscripts |
postrotate / endscript | Hook after rotate | postrotate ... endscript |
Time-based rotation relies on a periodic scheduler (cron/timer). Size-based rotation still needs periodic execution to notice that the size threshold has been crossed.
Practical configuration examples
Rotate an application log daily, keep 14 days, compress
Create /etc/logrotate.d/myapp:
/var/log/myapp/myapp.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
create 0640 myapp adm
}
Test (dry run):
sudo logrotate -d /etc/logrotate.d/myapp
Force rotation (use carefully):
sudo logrotate -f /etc/logrotate.d/myapp
-f ignores normal rotation checks and can rotate even when unnecessary. Use only for validation or when you understand the retention impact.
Rotate NGINX or OpenLiteSpeed logs with reload signaling
Many daemons can reopen logs on reload, which avoids copytruncate.
Example pattern:
/var/log/nginx/*.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
systemctl reload nginx >/dev/null 2>&1 || true
endscript
}
For OpenLiteSpeed, prefer its supported reload mechanism in postrotate if the logs are not reopening correctly; validate by checking that the new log file receives writes immediately after rotation.
Running and testing
Dry run (debug)
sudo logrotate -d /etc/logrotate.conf
Verbose run
sudo logrotate -v /etc/logrotate.conf
Force run (apply now)
sudo logrotate -f /etc/logrotate.conf
Check last rotation state
sudo tail -n 50 /var/lib/logrotate/status
Check scheduling
Cron
ls -la /etc/cron.daily/ | grep -i logrotate || true
systemd timer
systemctl list-timers | grep -i logrotate || true
systemctl status logrotate.timer 2>/dev/null || true
Troubleshooting
“Permission denied” rotating logs
Common causes:
- Log files owned by an app user, but rotation runs as root without
su - Incorrect
createowner/group - Directory permissions prevent creating new logs
Fix pattern:
- Add
su USER GROUPinside the block. - Ensure
create MODE OWNER GROUPmatches the service.
Example:
/var/log/myapp/myapp.log {
su myapp adm
create 0640 myapp adm
daily
rotate 14
missingok
notifempty
compress
}
Application keeps writing to the old rotated file
Cause: the application did not reopen the log file.
Fix options:
- Prefer
postrotateto send a reload/signal so the app reopens logs. - Use
copytruncateonly if the application cannot reopen logs.
copytruncate can lose log lines under load and can break log integrity for auditing. Use it only when signaling/reload is not possible.
Rotations not happening
Common causes:
- Scheduler not running (cron disabled, timer not active)
- Wrong file path glob
notifemptyprevents rotation because file is emptylogrotatestate file indicates it already rotated recently
Validate:
sudo logrotate -d /etc/logrotate.conf
sudo logrotate -d /etc/logrotate.d/<service>
Security notes
- Logs can contain secrets (session IDs, tokens, query strings). Restrict permissions and retention accordingly.
- Ensure rotated logs inherit appropriate permissions (
create), and do not become world-readable. - Consider encrypted off-host backups for compliance, but keep local retention bounded to reduce exposure.
If logs include authentication headers, personal data, or tokens, reduce retention and restrict access (file permissions and group membership).
Quick reference
| Task | Command |
|---|---|
| - | - |
| Dry run (no changes) | sudo logrotate -d /etc/logrotate.conf |
| Verbose run | sudo logrotate -v /etc/logrotate.conf |
| Force rotation | sudo logrotate -f /etc/logrotate.conf |
| View global config | sudo sed -n '1,200p' /etc/logrotate.conf |
| List per-service configs | sudo ls -la /etc/logrotate.d/ |
| Check scheduler (systemd) | systemctl status logrotate.timer |
| Check state file | sudo tail -n 50 /var/lib/logrotate/status |