What you will achieve
Rotate application and custom logs with logrotate — prevent disks filling from unbounded /var/log/app/*.log files.
1) Example config
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data adm
postrotate
systemctl reload myapp > /dev/null 2>&1 || true
endscript
}
2) Test dry run
sudo logrotate -d /etc/logrotate.d/myapp
sudo logrotate -f /etc/logrotate.d/myapp
3) journald size (related)
journalctl --disk-usage
sudo journalctl --vacuum-size=1G
Verify
ls -lh /var/log/myapp/
grep myapp /var/lib/logrotate/status
5) copytruncate for stubborn daemons
/var/log/app/app.log {
copytruncate
daily
rotate 7
}
Truncates in place — apps that cannot reopen log files keep writing without restart.
6) dateext for dated archives
dateext
dateformat -%Y%m%d
7) size-based rotation
size 100M
rotate 5
Global config
/etc/logrotate.conf sets defaults; per-app files in /etc/logrotate.d/ override. Run logrotate -d after edits — syntax errors silently skip rotation until fixed.
8) logrotate timer
systemctl list-timers | grep logrotate
Daily timer runs logrotate — if timer disabled, configs never fire despite correct syntax.
Prerequisites
Log paths exist and application reopens logs OR copytruncate configured. Root for /etc/logrotate.d/. Disk space for rotated .gz files. Service reload command known if postrotate needed.
Permission on rotate create
create 0640 www-data adm must match app user — wrong owner and app cannot append new logs after rotation.
sharedscripts for multiple logs
One postrotate reloading nginx after rotating multiple site logs — sharedscripts prevents reload storm per file.
application SIGUSR1
Some daemons reopen logs on SIGUSR1 not HUP — postrotate must match app docs. nginx uses reopen in postrotate script shipped in distro logrotate.d — copy pattern for custom apps.
hourly rotation
High traffic nginx may need hourly rotate in logrotate.conf with size trigger — daily insufficient when access.log hits gigabytes same afternoon.
logrotate status corruption
If rotation silently stops delete /var/lib/logrotate/status entry for broken stanza after fixing config syntax — status file tracks last rotation state.
maxsize trigger
maxsize 500M
rotate 7Rotate when log hits 500M even if daily not reached — burst traffic day fills disk before midnight cron.
olddir for archived logs
olddir /var/log/archive/nginxKeeps rotated gzip out of active log dir — simplifies backup include list.
su directive
su www-data www-data rotates log owned by app user when logrotate runs as root.
Rotation during deploy
Deploy scripts touching logrotate.d should run logrotate -d in CI — broken stanza discovered in pipeline not production midnight cron silence.