Production servers, self-hosted Docker containers, web servers (such as Nginx and Apache), and custom system services generate continuous streams of diagnostic logging in Ubuntu. Left unmanaged, active log files inside /var/log/ can quietly swell to tens of gigabytes, consuming critical disk space, slowing system I/O, and eventually crashing databases or preventing system boots when storage reaches 100%. Ubuntu automates log lifecycle maintenance using logrotate, an indispensable administrative daemon that rotates, compresses, and purges logs on predetermined schedules.
How Logrotate Operates in Modern Ubuntu
In Ubuntu 22.04 LTS and 24.04 LTS, logrotate is triggered automatically once per day via a systemd timer (logrotate.timer) rather than legacy cron. When triggered, logrotate evaluates configuration directives stored in /etc/logrotate.conf along with modular service files located in /etc/logrotate.d/. If a target log satisfies defined criteria (such as passing a time interval or exceeding a file size limit), logrotate moves the active log, creates a blank replacement, and compresses older cycles.
Understanding Default Configuration Files
Ubuntu organizes logrotate rules into two distinct tiers:
/etc/logrotate.conf: Establishes global defaults (such as weekly rotation, keeping 4 backlogs, and utilizing gzip compression)./etc/logrotate.d/: Contains modular configuration files for individual applications (such asrsyslog,dpkg,ufw, andnginx). Directives here override global settings for specific log paths.
How to Create a Custom Logrotate Configuration
Suppose you host a custom web application or Python backend that outputs logs to /var/log/myapp/app.log. Follow these steps to build an automated rotation policy:
Step 1: Create a Dedicated Service File
Open a terminal on your Ubuntu system and create a new configuration file inside /etc/logrotate.d/ using nano:
sudo nano /etc/logrotate.d/myapp
Step 2: Define Rotation Directives
Add the following configuration block tailored for high-volume logs:
/var/log/myapp/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
systemctl reload myapp.service > /dev/null 2>&1 || true
endscript
}
Directive Breakdown and Operational Explanation
Each directive in the configuration block serves a specific safeguard role:
- daily: Rotates the log once every 24 hours (alternatives include
weekly,monthly, or size-based triggers likesize 100M). - missingok: Prevents logrotate from throwing an error if the log file does not exist.
- rotate 14: Retains 14 rotated log files before automatically deleting the oldest backlog.
- compress: Compresses rotated files using
gzip(convertingapp.log.1toapp.log.2.gz), reducing disk consumption by up to 90%. - delaycompress: Defers compression of the most recently rotated log until the subsequent cycle, ensuring active processes writing trailing entries are not interrupted.
- notifempty: Skips rotation if the log file contains zero bytes, preventing unnecessary archive creation.
- create 0640 www-data adm: Creates the new empty log immediately after rotation with specified file permissions, owner user, and group.
- postrotate / endscript: Executes shell commands once rotation finishes. This sends a reload signal to the running application daemon so it releases the old file descriptor and begins writing to the newly created log file.
Testing and Validating Logrotate with Dry Runs
Never wait until an outage to discover a syntax error in your logrotate configuration. Test your rules safely using the debug flag:
sudo logrotate -d /etc/logrotate.d/myapp
The -d (debug) flag performs a comprehensive dry run. It outputs exact actions logrotate would take—including file checks, permission assignments, and command executions—without actually altering, moving, or compressing any files.
Forcing an Immediate Rotation
If you wish to test live file rotation immediately without waiting for the daily timer, use the -f (force) flag:
sudo logrotate -f /etc/logrotate.d/myapp
Verify that your log was rotated by listing directory contents:
ls -la /var/log/myapp/
You should see the original log renamed to app.log.1 alongside a fresh, empty app.log file with correct permissions.
Essential Logrotate Directives Reference
| Directive | Function | Typical Application |
|---|---|---|
size 50M |
Rotates as soon as file exceeds 50MB, regardless of schedule | High-traffic API endpoints |
copytruncate |
Copies log and truncates original in place | Apps that cannot release file handles on reload |
maxsize 500M |
Enforces rotation if size is breached before daily cycle | Runaway error prevention |
dateext |
Appends YYYYMMDD date format instead of integer numbers | Compliance and audit logging |
Troubleshooting Common Logrotate Failures
If logs fail to rotate or processes stop logging, check these frequent issues:
- Insecure File Permissions: Logrotate rejects configuration files that have loose permissions. Ensure your file inside
/etc/logrotate.d/is owned byroot:rootand has permissions0644. - Process Holds File Handle: If new logs remain empty while the old rotated log continues growing, the application was not signalled to reopen its file handle. Add a proper
postrotatereload command or usecopytruncate. - Checking Systemd Timer Status: Confirm that the automated daily trigger is active by checking
systemctl status logrotate.timer.
Establishing automated log rotation policies ensures your Ubuntu servers maintain consistent storage headroom, smooth diagnostic logging, and optimal performance across long-term deployments.