Why logrotate matters
Uncontrolled logs grow fast, eat disk, and break apps. logrotate keeps logs tidy by rotating, compressing, and pruning them on a schedule (daily/weekly) or when they reach a size threshold.
Prerequisites
- 
Linux server with logrotateinstalled (most distros include it).
- 
Root or sudo privileges to place configs in /etc/logrotate.d/.
- 
The path to your app’s log file (we’ll use /var/log/myapp/app.logas a generic example).
Where logrotate runs from (and when it rotates)
On most Linux distributions, logrotate is executed by cron or systemd timers:
- 
Cron: /etc/cron.daily/logrotate(usually runs once per day during early morning).
- 
systemd timer: logrotate.timer(similar cadence).
When should you expect a rotation?
- 
If you use daily, rotation happens the next time the daily logrotate job runs (typically once every 24h).
- 
If you use size 200Ktogether withdaily, rotation will trigger when either condition is met (size exceeded or the next daily run—whichever comes first).
- 
You can always force a rotation manually for testing (details below). 
Tip: Rotation happens when logrotate runs, not “immediately” as the file crosses the size threshold.
Understand who writes the log (this is critical)
- 
If your service runs as rootand writes/var/log/myapp/app.log, your logrotate stanza can usecreate 0644 root root.
- 
If your service runs as a non-root user (e.g., myapp:myapp), setcreateand optionallysuaccordingly so the app can keep writing after rotation.
Minimal, safe logrotate config (generic example)
Create /etc/logrotate.d/myapp:
Which option should you choose?
- 
Option A ( create) is best if your app reopens logs (e.g., onSIGHUPor after rotation hooks). This avoids losing log messages during the tiny window when files are moved/created.
- 
Option B ( copytruncate) is a pragmatic fallback when the app won’t reopen logs. It preserves the same inode so the app continues writing without noticing a rename. Trade-off: a very small chance of missing a few lines during copy/truncate.
Special case: rotating logs under world-writable directories (e.g., /tmp)
If your app logs to a path like /tmp/yourapp.log, logrotate will complain about insecure parent permissions. Add the su directive:
Best practice: avoid
/tmpfor persistent logs. Prefer/var/log/yourapp/yourapp.log.
Testing your configuration (safe & fast)
- 
Dry-run (no changes): 
- 
Force a rotation now (for verification): 
- 
Check results: - 
Active file: /var/log/myapp/app.log
- 
Archives: /var/log/myapp/app.log-20250919.gz(date may vary) or numbered files like.1,.2.gz, depending on your settings.
 
- 
If your app supports it, send a reload after rotation so it reopens the file:
Common directives you’ll actually use
- 
daily|weekly|monthly— cadence for scheduled rotation.
- 
size 200K— rotate when file exceeds this size (combine withdailyif you want whichever comes first).
- 
rotate 7— keep N archives; older are removed.
- 
compress/delaycompress— compress older archives; delay avoids compressing the newest rotated file (helpful for tooling).
- 
missingok— don’t error if the file is absent.
- 
notifempty— skip empty files.
- 
create 0644 USER GROUP— create a new log after rotation with these permissions/ownership.
- 
copytruncate— copy current log to archive and truncate the original (keeps inode).
- 
dateextanddateformat— use dates in archive names:
Troubleshooting (fix these fast)
“unknown unit ‘t’” near size 200k
Cause: extra characters on the line (often Windows CRLF or comment glued to the number).
Fix:
“skipping … parent directory has insecure permissions”
Cause: the log’s parent directory is world-writable (e.g., /tmp).
Fix: add su USER GROUP inside the block, or move logs to /var/log/....
App stops logging after rotation
Cause: the app holds the old file handle and does not reopen logs.
Fix: use copytruncate, or send SIGHUP, or configure the app to reopen logs after rotation.
Permissions wrong after rotation
Cause: mismatched create settings.
Fix: ensure create MODE USER GROUP matches the user/group that writes the log.
Example: size-only rotation (no daily)
Rotate purely by size and keep 14 days of archives:
Expectation: The next time the system’s logrotate job runs, if the file is ≥5 MB, it rotates; otherwise it doesn’t. It’s evaluated on each run.
Example: add pre/post hooks
You can run commands before or after rotation:
     prerotate
          /usr/bin/logger “About to rotate myapp logs”
     endscript
     postrotate
          /bin/systemctl reload myapp.service >/dev/null 2>&1 || true
     endscript
}
Quick checklist
- 
Confirm who writes the log (user/group). 
- 
Choose between create(preferred) orcopytruncate(fallback).
- 
Set sane retention: rotate 7+compress.
- 
Add sizeand/ordailydepending on growth profile.
- 
If under world-writable dirs (e.g., /tmp), addsu USER GROUP.
- 
Test with -d(dry-run) and then-f(force).
- 
If supported, reload your service after rotation. 
Frequently asked questions
Q: Will logrotate cut my log exactly at 200 KB instantly?
A: No. logrotate acts when it runs (daily/systemd schedule). It checks conditions (e.g., size). If met, it rotates then.
Q: Do I need copytruncate?
A: Only if your app can’t reopen logs after rotation. Prefer create + service reload for cleaner rotation.
Q: Can I keep only the last N lines in the active file?
A: That’s not logrotate’s model. You can approximate via a cron job using tail -n 100 file > tmp && mv or integrate a prerotate script.
Q: My logs live in /tmp. Is that OK?
A: It works with su, but /tmp is often cleaned on reboot. Prefer /var/log/... for persistence and hygiene.
Final thoughts
With a small, correct stanza in /etc/logrotate.d/, you’ll prevent runaway log growth and keep your system stable. Start simple: daily + size + rotate + compress and the right permissions for your app’s user. Then refine with hooks and naming options as your needs evolve.