How to Configure Logrotate for Application Logs on RHEL 7
Log files are essential for diagnosing problems and auditing system activity, but left unmanaged they will silently consume all available disk space and eventually bring a server to a halt. Logrotate is the standard tool on RHEL 7 for automating log file rotation, compression, and pruning. It runs daily as a cron job, reads configuration files from /etc/logrotate.d/, and applies rules you define — rotating files by age or size, compressing old logs, executing post-rotation commands to signal applications, and generating date-stamped archive filenames. This guide covers every major configuration option, size-based and date-based rotation strategies, manual execution, debugging techniques, and the relationship between logrotate and rsyslog.
Prerequisites
- RHEL 7 server with root or sudo access
- Logrotate installed — it is included in the base installation; verify with
rpm -q logrotate - An application writing log files to a known path (examples here use nginx and a custom application)
- Basic familiarity with the application’s signal handling (most daemons support
SIGUSR1orHUPto reopen log files)
Step 1: Understand How Logrotate Works on RHEL 7
Logrotate is invoked by a daily cron job defined in /etc/cron.daily/logrotate. This script runs once per day, typically in the early morning, and processes every configuration file it finds in /etc/logrotate.d/ as well as the global defaults in /etc/logrotate.conf. The global file sets system-wide defaults; files in /etc/logrotate.d/ override or extend those defaults on a per-application basis.
# View the main logrotate configuration
cat /etc/logrotate.conf
# List all per-application configuration files
ls -la /etc/logrotate.d/
Logrotate maintains state in /var/lib/logrotate/logrotate.status, which records the last time each log file was rotated. This prevents double-rotation if the tool is accidentally run twice in the same day.
Step 2: Create a Logrotate Configuration for Your Application
Drop a file named after your application into /etc/logrotate.d/. The file name is arbitrary — use something descriptive. Here is a comprehensive configuration for a custom application that writes to /var/log/myapp/:
cat > /etc/logrotate.d/myapp <<'EOF'
/var/log/myapp/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0644 myapp myapp
dateext
dateformat -%Y%m%d
sharedscripts
postrotate
# Signal the application to reopen its log file handles
[ -f /var/run/myapp.pid ] && kill -USR1 $(cat /var/run/myapp.pid) || true
endscript
}
EOF
What Each Directive Does
- daily — Rotate once per day. Alternatives are
weekly,monthly, andyearly. - rotate 14 — Keep 14 rotated copies before deleting the oldest. Combined with
daily, this retains two weeks of history. - compress — Compress rotated log files with gzip. This typically reduces file size by 70–90% for text logs.
- delaycompress — Postpone compression of the most recently rotated file by one rotation cycle. This is essential for applications that keep the old file descriptor open briefly after rotation — without it, the application might still be writing to the file being compressed.
- missingok — Do not report an error if the log file does not exist (useful during application downtime or initial setup).
- notifempty — Skip rotation if the log file is empty. Prevents cluttering the archive with zero-byte compressed files.
- create 0644 myapp myapp — After rotation, immediately create a new empty log file with the specified permissions and ownership so the application can continue writing without interruption.
- dateext — Append the rotation date to the archived filename instead of a plain numeric suffix (e.g.,
app.log-20260517instead ofapp.log.1). - dateformat -%Y%m%d — Format string for the date extension. The leading dash separates the base name from the date.
- sharedscripts — When the pattern matches multiple log files, run the
postrotatescript only once rather than once per file. - postrotate / endscript — Shell commands executed after rotation. Used to signal the application to reopen its log files.
Step 3: Configure Nginx Log Rotation
Nginx uses SIGUSR1 to reopen its log files. RHEL 7’s nginx package installs its own logrotate configuration at /etc/logrotate.d/nginx. Review and customise it:
cat > /etc/logrotate.d/nginx <<'EOF'
/var/log/nginx/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 nginx adm
dateext
dateformat -%Y%m%d
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 $(cat /var/run/nginx.pid)
fi
endscript
}
EOF
For Apache (httpd), which uses SIGUSR1 via the apachectl graceful restart mechanism, the postrotate script should instead use:
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>&1 || true
endscript
Step 4: Use Size-Based Rotation
Time-based rotation is predictable but unsuitable for high-volume log sources that can fill a disk within hours. Use the size directive to trigger rotation when a file reaches a threshold regardless of time:
# /etc/logrotate.d/myapp-highvolume
/var/log/myapp/access.log {
size 100M
rotate 10
compress
delaycompress
missingok
notifempty
create 0644 myapp myapp
dateext
sharedscripts
postrotate
[ -f /var/run/myapp.pid ] && kill -USR1 $(cat /var/run/myapp.pid) || true
endscript
}
Size values can be specified in bytes (100k), kilobytes (100k), megabytes (100M), or gigabytes (1G). Note that size-based rotation only triggers when logrotate runs — by default once per day. For true size-based rotation at sub-daily intervals, combine size with a more frequent cron job:
# Run logrotate every hour
echo "0 * * * * root /usr/sbin/logrotate /etc/logrotate.conf"
> /etc/cron.d/logrotate-hourly
Step 5: Use dateext for Date-Stamped Archive Filenames
Without dateext, logrotate names archives app.log.1, app.log.2, and so on — renaming every file on each rotation cycle, which makes scripted log searches difficult. With dateext, each archive gets a unique, human-readable name:
# Result with dateext + dateformat -%Y%m%d:
ls -lh /var/log/myapp/
# app.log ← current log
# app.log-20260517.gz ← yesterday's log, compressed
# app.log-20260516.gz
# app.log-20260515.gz
If you rotate more than once per day, add the time component to avoid filename collisions:
dateformat -%Y%m%d-%H%M%S
Step 6: Run Logrotate Manually
To trigger an immediate rotation without waiting for the daily cron job, use the -f (force) flag. This is useful after deploying an application or when disk space is running low:
# Force rotation of all configurations
logrotate -f /etc/logrotate.conf
# Force rotation of a specific configuration only
logrotate -f /etc/logrotate.d/myapp
The -f flag overrides the notifempty and recency checks, so rotation happens even if logrotate already ran today.
Step 7: Debug Logrotate Configuration
The -d (debug) flag runs logrotate in dry-run mode — it prints every action it would take without actually rotating, compressing, or executing postrotate scripts. Use it to validate a new configuration before it runs in production:
# Debug mode — no files are modified
logrotate -d /etc/logrotate.d/myapp
Sample output shows which files match, whether rotation is needed, and what the postrotate script would execute:
reading config file /etc/logrotate.d/myapp
Allocating hash table for state file, size 64 entries
Handling 1 logs
rotating pattern: /var/log/myapp/*.log after 1 days (14 rotations)
empty log files are not rotated, old logs are removed
switching euid to 0 and egid to 0
considering log /var/log/myapp/app.log
log needs rotating
For more verbose output, combine -d with -v:
logrotate -dv /etc/logrotate.d/myapp
If logrotate reports an error about a configuration file, check file syntax carefully — a common mistake is omitting the closing brace or misquoting a path with spaces:
# Validate configuration syntax
logrotate --debug /etc/logrotate.d/myapp 2>&1 | head -20
Step 8: Logrotate and rsyslog Interaction
The system logger rsyslog writes to /var/log/messages, /var/log/secure, /var/log/maillog, and other files. These are managed by the /etc/logrotate.d/syslog configuration that ships with RHEL 7. After rotating, logrotate must signal rsyslog to reopen its file descriptors:
# The default /etc/logrotate.d/syslog postrotate script:
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
On RHEL 7 with rsyslog, you can also use systemctl to send the signal reliably:
postrotate
/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
View the current syslog logrotate configuration to understand how RHEL 7 handles its own system logs:
cat /etc/logrotate.d/syslog
Conclusion
Logrotate is a simple but powerful tool that, once correctly configured, runs silently in the background and ensures your log directories never fill the disk. By creating a dedicated configuration file in /etc/logrotate.d/ for each application, combining compress with delaycompress, using dateext for human-readable archive names, and writing accurate postrotate scripts to signal your applications, you establish a maintainable and reliable log management strategy. The -d debug flag and -f force flag give you the confidence to test changes and trigger immediate rotations when needed, while the interaction with rsyslog ensures system logs are handled consistently alongside your application logs.