Manage Log Files with Logrotate on VPS to Prevent Disk Full
Log files are a silent killer—they can fill your disk without you noticing, especially on small VPS instances with limited storage. Logrotate solves this problem by automatically rotating, compressing, and deleting old logs. It comes built-in with Ubuntu/Debian; you just need to configure it properly.
Logrotate Structure
/etc/logrotate.conf— main configuration file/etc/logrotate.d/— service-specific configuration directory- Runs daily via cron at
/etc/cron.daily/logrotate
Example Config for Nginx
/var/log/nginx/*.log {
daily # rotate daily
missingok # don't error if file is missing
rotate 14 # keep 14 rotations (14 days)
compress # compress with gzip
delaycompress # compress the previous rotation (not current)
notifempty # don't rotate if file is empty
sharedscripts # run script once for all logs
postrotate
nginx -s reopen
endscript
}
Config for MySQL / MariaDB
/var/log/mysql/*.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 640 mysql adm
postrotate
mysqladmin flush-logs
endscript
}
Config for General Application Logs
/var/www/myapp/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
dateext # add date to backup filename
dateformat -%Y%m%d
copytruncate # copy then truncate instead of rename (if app keeps file open)
}
Test Config Without Actually Rotating
logrotate -d /etc/logrotate.d/nginx
-d is dry-run mode—it shows what will happen without touching actual files.
Force Rotate Immediately
logrotate -f /etc/logrotate.d/nginx
View Rotated Logs
ls -lh /var/log/nginx/
# You'll see .gz files in date order
# access.log.1, access.log.2.gz, access.log.3.gz ...
Check Disk Usage Before and After
# Check size of log directory
du -sh /var/log/*
# Check overall disk usage
df -h
copytruncate instead. The downside is you may lose a small amount of log data during the copy operation.Summary
Set up logrotate once and it works on its own from then on—no more worrying about disk space being consumed by logs. Regularly check df -h and consider setting up alerts when disk usage exceeds 80%.
Verify Logrotate is Working Correctly
# Check status log to see when rotation last ran
cat /var/lib/logrotate/status | grep nginx
# View logrotate's own logs
cat /var/log/syslog | grep logrotate
# Check config syntax
logrotate -d /etc/logrotate.d/nginx
# -d is dry-run mode—doesn't touch actual files
du -sh /var/log/* to see which service is consuming the most disk space, then adjust that service's rotation frequency accordingly.Common Issues & Troubleshooting
Error: "error: skipping ... because parent directory has insecure permissions"
The owner of /etc/logrotate.d/ or the config file is incorrect:
# Check permissions
ls -la /etc/logrotate.d/
# Must be root:root and 644
# Fix it
chown root:root /etc/logrotate.d/myapp
chmod 644 /etc/logrotate.d/myapp
Logs disappear after rotation / service can't write logs
Some services keep a file handle open. Use copytruncate or send a signal to the process:
# Use copytruncate for processes that keep file handles open
/var/www/myapp/logs/*.log {
daily
rotate 30
compress
copytruncate # copy instead of rename
missingok
notifempty
}
Logrotate not running on schedule (cron not executing)
# Check cron service status
systemctl status cron
# or crond on AlmaLinux
# Verify logrotate exists in cron.daily
ls /etc/cron.daily/ | grep logrotate
# Run manually to test
logrotate -f /etc/logrotate.conf
Error: "nginx: error while loading shared libraries" after postrotate
The postrotate script has an error—nginx reload failed. Test nginx config first:
# Test nginx config
nginx -t
# If using Apache instead, fix the postrotate section
postrotate
apache2ctl graceful 2>/dev/null || true
endscript
Frequently Asked Questions
How many days should I set for rotation?
It depends on your log volume and available disk space. Recommended: for web access logs, set rotation to daily with 14 rotations (2 weeks) on small VPS. For application logs, follow your business retention requirements.
How do I read gzip-compressed logs?
zcat access.log.2.gz | head -50
zgrep "404" access.log.2.gz
# or gunzip first, then read normally
Where do I create custom logrotate configs?
Create a new file in /etc/logrotate.d/ named after your service, such as /etc/logrotate.d/myapp. Logrotate automatically reads all files in this directory.