Your server has been running fine for three months. Then one morning nothing works — SSH is slow, services throw errors, disk at 100%.
df -h
You dig in and find /var/log is 40GB. One log file has been growing unchecked since day one. logrotate ships on every Debian/Ubuntu server. Most people ignore it until it bites them.
Find what's eating your disk right now
sudo du -sh /var/log/* | sort -rh | head -20
If you find a multi-GB file with no rotation config, fix it today. Don't wait for a 3am alert.
How it works
logrotate runs daily via cron (/etc/cron.daily/logrotate). It reads /etc/logrotate.conf and everything in /etc/logrotate.d/. Drop a file there for each app you want to manage.
ls /etc/logrotate.d/
nginx, rsyslog, apt — probably already there. Check what nginx is doing: cat /etc/logrotate.d/nginx
Write your own config
App writing to /var/log/myapp/app.log:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
systemctl reload myapp 2>/dev/null || true
endscript
}
What each option does:
daily— rotate every day.weeklyandmonthlyalso valid.rotate 14— keep 14 old files, delete the restcompress— gzip rotated filesdelaycompress— don't compress the most recent rotated file (some apps keep it open)missingok— don't error if the log file is missingnotifempty— skip rotation if the file is emptycreate 0640 www-data www-data— create a new empty log file with these permissions after rotationpostrotate— reload the app so it starts writing to the new file
Test before you trust it
sudo logrotate -d /etc/logrotate.d/myapp
-d is dry run — shows what would happen without doing it. If it says "log does not need rotating" that's fine, it's just not due yet.
Force a rotation now:
sudo logrotate -f /etc/logrotate.d/myapp
The postrotate gotcha that burns everyone
If your app doesn't get reloaded after rotation, it keeps writing to the old (now rotated) file. The new empty log stays empty. Logs go to the rotated copy. This catches people constantly.
Always add a postrotate that reloads your app or sends SIGHUP:
postrotate
kill -HUP $(cat /var/run/myapp.pid) 2>/dev/null || true
endscript
The || true prevents logrotate from erroring if the service isn't running.
Global defaults
/etc/logrotate.conf sets defaults for everything. Individual configs in /etc/logrotate.d/ override per-app.
cat /etc/logrotate.conf
Cap journald too
systemd's journal accumulates separately. Check and cap it:
sudo journalctl --disk-usage
sudo nano /etc/systemd/journald.conf
[Journal]
SystemMaxUse=500M
MaxRetentionSec=1month
sudo systemctl restart systemd-journald
Combined, logrotate + a journald cap keeps /var/log under control permanently.