What is logrotate?
When a server runs for a long time, log files under /var/log grow without bound. Left unchecked, the disk fills up and services stop; a multi-GB single log is hard even to search. logrotate is the standard tool that automates this: at a set interval or size it rotates logs into new files and compresses or deletes the old ones.
The basic idea of rotation looks like this.
app.log ←
app.log.1 ←
app.log.2.gz ←
app.log.3.gz
...When a new file is created, the numbers shift by one, and the oldest file beyond the retention limit is deleted.
How it works and when it runs
logrotate is not a daemon; it is a one-shot command that cron or a systemd timer runs once a day.
| Distro | Trigger |
|---|---|
| Traditional | /etc/cron.daily/logrotate |
| systemd-based | logrotate.timer → logrotate.service |
# systemd check
systemctl list-timers logrotate.timer
systemctl status logrotate.timerThe configuration entry point is /etc/logrotate.conf, which ends with include /etc/logrotate.d to load per-app configs. The standard practice is to put package- or application-specific settings as files under /etc/logrotate.d/.
Global defaults — /etc/logrotate.conf
#
weekly
# 4 ( 4)
rotate 4
# after file
create
# file (app.log-20260618)
dateext
# file
compress
# settings
include /etc/logrotate.dIf an individual config under /etc/logrotate.d repeats the same directive, it overrides the global value.
Writing a per-app config — /etc/logrotate.d/myapp
A practical example for a web application log.
/var/log/myapp/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
dateext
create 0640 appuser appgroup
sharedscripts
postrotate
systemctl reload myapp >/dev/null 2>&1 || true
endscript
}What each directive does:
| Directive | Role |
|---|---|
daily / weekly / monthly | Rotation interval |
rotate 14 | Keep 14 copies, then delete |
missingok | Skip without error if the log file is missing |
notifempty | Do not rotate if the file is empty |
compress | gzip-compress rotated files |
delaycompress | Delay compression of the most recently rotated file by one cycle |
dateext | Use a date suffix instead of a sequence number |
create 0640 user group | Create the new log with the given mode and ownership |
sharedscripts | Run scripts once for the whole wildcard match, not once per file |
postrotate ... endscript | Commands to run immediately after rotation |
When you need to unpack rotated .gz logs or bundle several logs for handoff, see Linux tar, gzip, and zstd decompression cheat sheet.
Size-based rotation
Use this when you want to cut by size rather than time.
/var/log/nginx/access.log {
size 100M
rotate 10
compress
missingok
create 0640 www-data adm
postrotate
# nginx file
[ -f /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}| Directive | Meaning |
|---|---|
size 100M | Rotate when the file exceeds 100MB (interval is ignored; size is checked on every run) |
maxsize 100M | Rotate even before the interval if this size is exceeded |
minsize 10M | Do not rotate at the interval if the file is smaller than this |
Using size alone ignores time conditions such as daily/weekly. If you want “weekly, or whenever it exceeds 100MB”, combine weekly with maxsize 100M.
create vs copytruncate
These are the two most important rotation strategies. Choose based on how the application handles its log file.
| Method | Behavior | Best when |
|---|---|---|
create (default) | Renames the existing file with mv and creates a new one | The app can receive a reopen signal (SIGHUP, etc.) from postrotate |
copytruncate | Copies the original, then truncates it to 0 bytes | You cannot restart or signal the app and it keeps the file handle open |
/var/log/legacy-app/output.log {
daily
rotate 7
compress
copytruncate
}If you use create but never send a reopen signal, the app keeps writing to the old file handle that was mv'd (already renamed). The new app.log stays empty and disk usage never drops. If the app cannot be signaled, use copytruncate, but be aware that logs written in the brief window between copy and truncate can be lost.
prerotate / postrotate scripts
Run commands before or after rotation. The usual use is signaling a service to open the new file.
postrotate
# systemd reload
systemctl reload rsyslog >/dev/null 2>&1 || true
endscriptWithout sharedscripts, the script runs once per file matched by the wildcard. A service reload usually needs to happen only once, so pairing it with sharedscripts is the common pattern.
Testing and debugging
After changing a config, verify immediately instead of waiting for cron.
# 1) ( X) —
logrotate --debug /etc/logrotate.d/myapp
# 2) (/ when)
sudo logrotate --force /etc/logrotate.d/myapp
# 3) settings run
sudo logrotate --force /etc/logrotate.conf
# 4) when check
cat /var/lib/logrotate/logrotate.status--debug includes --verbose and does not change anything. It is the safe first step when checking a config on a production server. If rotation is not happening, check whether that log's last rotation date was updated in the status file.
Common problems
| Symptom | Cause / fix |
|---|---|
| Rotation ran but disk usage did not drop | create without a reopen signal → use copytruncate or add a postrotate signal |
| New log cannot be created due to permissions | Set create mode/owner and check parent directory permissions |
| Config is ignored | Execute bit or extension issues on the /etc/logrotate.d/ file, or it is not included from .conf. Watch for extra . (dots) in the filename |
| "skipping ... because parent directory has insecure permissions" | Add an su user group directive or fix directory permissions |
| One compressed file seems missing | Caused by delaycompress (the newest rotated file is compressed on the next cycle) — expected behavior |
Recap
| Item | Key point |
|---|---|
| Who runs it | cron.daily or logrotate.timer (not a daemon) |
| Config location | Global /etc/logrotate.conf, per-app /etc/logrotate.d/ |
| Schedule | daily/weekly/monthly or size/maxsize |
| Retention count | rotate N |
| Compression | compress + delaycompress |
| New file handling | create (needs a signal) vs copytruncate (apps that cannot be signaled) |
| Post-processing | postrotate ... endscript + sharedscripts |
| Verification | logrotate --debug, --force |
Because logrotate ships on almost every Linux server, getting into the habit of dropping a config file into /etc/logrotate.d/ whenever you deploy a new service is the most reliable way to prevent outages caused by a full disk.
AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us
Questions & answers
Ask a question about this guide. We'll review and reply.