How to Configure Log Rotation with logrotate on RHEL 7
Log files are essential for diagnosing system problems, tracking security events, and auditing application behavior. However, without proper management, log files grow without bound and can fill your disk, causing service outages and making historical logs difficult to navigate. logrotate is the standard log rotation utility on RHEL 7. It automatically renames, compresses, and eventually discards old log files on a schedule you define. Understanding how to configure logrotate — for both system logs and your own application logs — is a foundational system administration skill that prevents countless disk-full emergencies.
Prerequisites
- A running RHEL 7 system with root or sudo access
- logrotate installed (it is included in the default RHEL 7 base installation)
- Basic familiarity with text editors and the command line
Verify logrotate is installed:
rpm -q logrotate
If not present:
sudo yum install logrotate
Step 1: Understanding How logrotate Works
logrotate is typically invoked daily by a cron job installed at /etc/cron.daily/logrotate. When it runs, it reads its main configuration file and all drop-in files, then processes each log file according to the matching rules. The core behavior is:
- Rename the current log file with a date suffix or numeric extension (e.g.,
messages.1ormessages-20260517). - Optionally compress the renamed file (using gzip by default).
- Signal the application to reopen its log file (via a
postrotatescript), so it begins writing to a fresh file. - Remove log files older than the configured retention count.
The rotation schedule and behavior are entirely defined in configuration files — logrotate itself has no hardcoded rules about any specific log.
Step 2: The Main Configuration File — /etc/logrotate.conf
The global defaults are set in /etc/logrotate.conf. View its contents:
cat /etc/logrotate.conf
On a default RHEL 7 installation, it looks similar to this:
# rotate log files weekly
weekly
# keep 4 weeks worth of backlogs
rotate 4
# create new (empty) log files after rotating old ones
create
# use date as a suffix of the rotated file
dateext
# compress rotated log files
compress
# RPM packages drop log rotation information into this directory
include /etc/logrotate.d
# no packages own wtmp and btmp — rotate them here
/var/log/wtmp {
monthly
create 0664 root utmp
minsize 1M
rotate 1
}
/var/log/btmp {
missingok
monthly
create 0600 root utmp
rotate 1
}
The include /etc/logrotate.d directive tells logrotate to read all configuration files in that directory, which is where application-specific rules live.
Step 3: Understanding the /etc/logrotate.d/ Directory
Almost every package that installs a log file also installs a logrotate configuration in /etc/logrotate.d/. View the installed configurations:
ls /etc/logrotate.d/
Typical output on a RHEL 7 web server:
httpd nginx mysql syslog yum ...etc
Look at the Apache/httpd configuration as an example:
cat /etc/logrotate.d/httpd
/var/log/httpd/*log {
missingok
notifempty
sharedscripts
delaycompress
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
Step 4: Core Rotation Directives Explained
The following directives are the building blocks of any logrotate configuration:
Rotation Frequency
daily # Rotate every day
weekly # Rotate once a week
monthly # Rotate once a month
yearly # Rotate once a year
Retention Count
rotate 7 # Keep 7 rotated copies before deleting the oldest
Size-Based Rotation
size 100M # Rotate when file exceeds 100 MB (regardless of schedule)
minsize 1M # Only rotate if file is at least 1 MB (combined with schedule)
maxsize 500M # Force rotation if file exceeds this size even before the schedule
Compression
compress # Compress rotated files with gzip
nocompress # Do not compress
delaycompress # Delay compression until the next rotation cycle (useful for services
# that may still be writing to the just-rotated file)
compresscmd /usr/bin/bzip2 # Use bzip2 instead of gzip
compressext .bz2 # Set the compressed file extension
File Handling
missingok # Do not report an error if the log file is missing
notifempty # Do not rotate if the log file is empty
create # Create a new empty log file after rotation
create 0640 root adm # Create with specific permissions, owner, group
nocreate # Do not create a new log file after rotation
copytruncate # Copy log then truncate original (for apps that can't reopen logs)
Date-Based Naming
dateext # Append a date instead of a number (e.g., logfile-20260517.gz)
dateformat -%Y%m%d # Customize the date format
Script Hooks
postrotate
/bin/systemctl reload myservice > /dev/null 2>&1 || true
endscript
prerotate
echo "About to rotate" >> /var/log/rotation.log
endscript
sharedscripts # Run postrotate/prerotate only once even if multiple files matched
Step 5: Creating a Custom logrotate Configuration
Suppose you have a custom application writing logs to /var/log/myapp/app.log. Create a dedicated logrotate configuration for it:
sudo vi /etc/logrotate.d/myapp
Paste the following:
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 myappuser myappgroup
dateext
dateformat -%Y%m%d
sharedscripts
postrotate
/bin/systemctl reload myapp.service > /dev/null 2>&1 || true
endscript
}
Breaking down this configuration:
- Rotates all
.logfiles in/var/log/myapp/daily. - Keeps 14 days of history.
- Compresses old files, but delays compressing the most recent rotation (in case the app is still writing to it briefly after rotation).
- Skips rotation if the file is missing or empty.
- Creates a new empty log file owned by the application’s user and group.
- Appends date-formatted suffixes to rotated files.
- Sends a reload signal to the service so it reopens its log file descriptor.
Step 6: Testing logrotate Configuration
Before relying on a new configuration, always test it to catch syntax errors and verify behavior.
Dry Run with -d (Debug Mode)
The -d flag runs logrotate in debug mode. It reads all configuration, shows what it would do, but makes no changes:
sudo logrotate -d /etc/logrotate.d/myapp
Review the output carefully. It will show which files match, whether rotation conditions are met, and what actions would be taken.
Force Rotation with -f
To force an immediate rotation regardless of whether the rotation condition (daily, size, etc.) is met:
sudo logrotate -f /etc/logrotate.d/myapp
To force a full rotation of all configurations:
sudo logrotate -f /etc/logrotate.conf
Verbose Mode
Combine -v with -f for detailed output:
sudo logrotate -vf /etc/logrotate.d/myapp
Checking the State File
logrotate tracks when it last rotated each file in a state file at /var/lib/logrotate/logrotate.status (or /var/lib/logrotate.status on some RHEL 7 versions):
cat /var/lib/logrotate/logrotate.status | grep myapp
Example output:
"/var/log/myapp/app.log" 2026-5-17-6:0:0
You can delete entries from this file to force logrotate to treat a file as never rotated, or modify timestamps to test time-based rotation logic.
Step 7: Managing the systemd Journal Size
On RHEL 7, systemd’s journal (journald) maintains its own separate log store and is not managed by logrotate. By default, the journal is stored in /run/log/journal/ (volatile, lost on reboot) unless persistent storage is configured. Control its size through /etc/systemd/journald.conf:
sudo vi /etc/systemd/journald.conf
Relevant size-limiting directives:
[Journal]
# Maximum total disk space the journal may use
SystemMaxUse=500M
# Leave at least this much free on the filesystem
SystemKeepFree=1G
# Maximum size of an individual journal file before it is rotated internally
SystemMaxFileSize=50M
# Maximum time to keep journal entries
MaxRetentionSec=1month
# For volatile (in-memory) journal:
RuntimeMaxUse=100M
After editing, restart journald to apply the changes:
sudo systemctl restart systemd-journald
To manually vacuum the journal down to a target size:
# Remove journal files until total size is under 200MB
sudo journalctl --vacuum-size=200M
# Remove journal files older than 2 weeks
sudo journalctl --vacuum-time=2weeks
# Show current journal disk usage
sudo journalctl --disk-usage
Step 8: Troubleshooting Common logrotate Issues
A few common problems and their solutions:
Log file not being rotated
Check the state file to see the last rotation time. If it was rotated recently, the schedule has not elapsed. Use -f to force it for testing.
Application still writing to old log file after rotation
The postrotate script must signal the application to close and reopen its log file descriptor. If the application does not support signals for this, use copytruncate instead:
/var/log/myapp/*.log {
daily
rotate 14
compress
copytruncate
missingok
notifempty
}
copytruncate copies the log to a rotated file and then truncates the original, so the running application never loses its file descriptor. Note there is a brief window where log entries may be lost between the copy and the truncate.
Permission denied errors in postrotate
Ensure the command in postrotate uses full paths and that logrotate (running as root via cron) has permission to execute it.
Conclusion
logrotate is a simple but powerful tool that prevents disk exhaustion from runaway log files on RHEL 7 systems. You have learned how the /etc/logrotate.conf global configuration works, how to place application-specific rules in /etc/logrotate.d/, the meaning of all major rotation directives, how to create a custom configuration for your own application’s logs, and how to test configurations safely before they go live. Combine logrotate management for traditional log files with proper journald size limits for systemd-managed services, and you will have comprehensive log lifecycle control across your entire RHEL 7 system. Schedule a periodic review of your retention settings as your system grows to ensure disk usage remains within acceptable bounds.