Logs grow forever unless something trims them. A single noisy app log can fill a VPS disk and take down MySQL and the website with it. Logrotate rotates, compresses and deletes old log files on a schedule, and journald has its own size limits. This guide sets up both.
Before you start
- Root access. Logrotate is installed by default on Ubuntu, Debian, AlmaLinux and Rocky and runs daily from a systemd timer or cron.
- Check current disk use:
df -h.
Find what is using space
du -sh /var/log/* 2>/dev/null | sort -h | tailjournalctl --disk-usageAlso check app folders such as /var/www/*/storage/logs or ~/.pm2/logs.
How logrotate is configured
/etc/logrotate.conf: global defaults./etc/logrotate.d/: one file per service (nginx, mysql, rsyslog...). Add your own here.
Add a rule for your application
Create /etc/logrotate.d/myapp:
/var/www/myapp/storage/logs/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
maxsize 100M
create 0640 www-data www-data
sharedscripts
postrotate
systemctl reload php8.3-fpm > /dev/null 2>&1 || true
endscript
}| Directive | Meaning |
|---|---|
daily / weekly | How often to rotate |
rotate 14 | Keep 14 old files |
compress + delaycompress | Gzip old logs, but leave the most recent one uncompressed |
maxsize 100M | Rotate early if the file exceeds 100 MB |
create | Recreate the log with these permissions |
postrotate | Tell the app to reopen its log file |
copytruncate | For apps that cannot reopen logs: copy, then empty the original |
Test the rule
Dry run (shows what would happen):
logrotate -d /etc/logrotate.d/myappForce a rotation now:
logrotate -f /etc/logrotate.d/myappThe log folder should now contain app.log and app.log.1; compressed .gz files appear from the next rotation on.
Limit the systemd journal
Edit /etc/systemd/journald.conf:
[Journal]
SystemMaxUse=500M
MaxRetentionSec=1monthApply with systemctl restart systemd-journald. To free space immediately:
journalctl --vacuum-size=200MFree space from a huge log safely
Deleting a log that a process still has open does not free space until the process restarts. Truncate it instead:
truncate -s 0 /var/log/myapp/huge.logIf space is still missing after deleting files, find deleted-but-open files:
lsof +L1 | grep -i logRestart the process that holds them.
Troubleshooting
- error: skipping ... because parent directory has insecure permissions: add
su www-data www-datato the rule, matching the folder's owner. - Logs not rotating: check the timer with
systemctl status logrotate.timerand the state file/var/lib/logrotate/status. - App keeps writing to the rotated file: it never reopened the log. Add a
postrotatereload or usecopytruncate.
Logrotate FAQ
How long should I keep logs?
Two to four weeks covers most troubleshooting. Keep longer if security or legal requirements say so, ideally off the server.
Does logrotate work with Docker containers?
Container logs are handled by Docker's logging driver. Set max-size and max-file in /etc/docker/daemon.json instead.
Do I need this on cPanel hosting?
No. On cPanel servers, log rotation is handled by the server; you can choose whether to archive logs under cPanel → Metrics → Raw Access.
