Introduction / Why This Is Needed
Application and system logs in Linux grow relentlessly over time. If left unchecked, they can consume all available disk space, cause service failures, and complicate the search for specific events. Log rotation is the standard mechanism for automatically archiving, compressing, and deleting outdated records. Most Linux distributions use the logrotate utility for this purpose. Once configured, you will gain:
- Control over disk space usage.
- Simplified analysis thanks to structured archives.
- Automation of a routine task without administrator intervention.
This guide will show you how to configure logrotate for your applications on modern systems (Ubuntu, Debian, CentOS, Fedora).
Requirements / Preparation
Before you begin, ensure you have:
- Access to a Linux terminal with superuser privileges (
sudo). - The logrotate utility installed (usually pre-installed). Verify with:
logrotate --version - Knowledge of your application's log location. For example, for the Apache web server it's
/var/log/apache2/, for Nginx —/var/log/nginx/. If logs are stored in a non-standard location, find them usingfindor check your application's configuration. - Basic familiarity with text editors (
nano,vim) for editing configuration files.
Step-by-Step Instructions
Step 1: Verify logrotate Installation
Although logrotate typically comes with the system, it might be missing in minimal installations. Check the version:
logrotate --version
If the command is not found, install it:
- For Ubuntu/Debian:
sudo apt update sudo apt install logrotate - For CentOS/Rocky/Fedora:
sudo dnf install logrotate
After installation, recheck the version. Current versions (3.15+) support all modern options.
Step 2: Create a Configuration File
Logrotate uses two types of configurations:
- The global file
/etc/logrotate.conf— sets general parameters (e.g., how often to run). - Files in
/etc/logrotate.d/— contain settings for specific applications. This is the preferred method as it doesn't interfere with package updates.
Create a file for your application. For example, for a custom application myapp with logs in /var/log/myapp/:
sudo nano /etc/logrotate.d/myapp
Paste the basic configuration:
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 644 root root
sharedscripts
postrotate
systemctl reload myapp.service > /dev/null 2>&1 || true
endscript
}
Parameter Explanation:
/var/log/myapp/*.log— path to logs (wildcards supported).daily— rotate every day. Other options:weekly,monthly,yearly.rotate 7— keep 7 archives (the oldest are deleted after this).compress— compress archives usinggzip(files get.gzextension).delaycompress— compress not immediately, but on the next cycle (convenient if the application is still writing to the previous file).missingok— don't throw an error if the log file is missing.notifempty— don't rotate empty files.create 644 root root— create a new log file after rotation with specified permissions and owner.sharedscripts— runpostrotateonly once for all files, not for each.postrotate/endscript— commands after rotation. Here we reload themyappservice so it starts writing to a new file. If the service doesn't require reloading, you can remove this block.
Save the file (Ctrl+O, Enter, Ctrl+X in nano).
Step 3: Customize Rotation Settings for Your Needs
Edit the config considering your specifics:
- Rotation frequency: if logs are very active, use
hourly(but requires additional cron/systemd setup). For most cases,dailyis sufficient. - Retention:
rotate 30— keep a month's worth. Consider available space: compression reduces size by 5-10x. - Size-based instead of time-based: if you need to rotate by size, replace
dailywith:
This means rotate when 100 MB is reached.size 100M - Deletion without compression: if compression isn't needed, remove
compressanddelaycompress. - Multiple log directories: you can specify multiple paths or use wildcards, e.g.:
/var/log/myapp/*.log /var/log/myapp/audit/*.log { ... } - Permissions for new files: the
createparameter should match how the application expects to see files. Usually644for regular logs, but for secured logs600may be required.
Important: If the application writes logs directly to /dev/stdout (e.g., Docker containers), logrotate might not work — in such cases, rotation must be configured at the orchestrator level.
Step 4: Test the Configuration
Don't wait for the next scheduled run — check the config immediately:
sudo logrotate -d /etc/logrotate.conf
The -d flag enables dry-run mode: logrotate will show what it would do without making changes.
In the output, look for:
reading config file /etc/logrotate.d/myapp— config loaded.rotating pattern: /var/log/myapp/*.log— path recognized.old log is removedorlog does not need rotating— expected behavior.- Errors:
error: error accessing /var/log/myapp/...— issue with permissions or path.
If everything looks good, perform a forced rotation for testing (but be cautious — this will actually move files):
sudo logrotate -vf /etc/logrotate.conf
Flags:
-v— verbose output.-f— force run even if it's not time.
Then check the /var/log/myapp/ directory — archives like myapp.log.1.gz and a new myapp.log should appear.
Step 5: Check Status and Logs
Logrotate records when each file was last rotated in a status file (default /var/lib/logrotate/status). View it:
sudo cat /var/lib/logrotate/status
You'll see entries like:
/var/log/myapp/myapp.log 2026-2-16-10:30:1
This confirms rotation occurred.
Also check cron logs or systemd to ensure the task runs on schedule:
- For cron-based systems (Ubuntu/Debian before recent versions):
Or check files ingrep logrotate /var/log/cron.log/etc/cron.daily/— there should be alogrotatescript. - For systemd-based systems (CentOS 8+, Fedora, Ubuntu 22.04+):
The timer is usually set to run daily. To change the schedule, edit thesystemctl status logrotate.timerlogrotate.timerunit (viasystemctl edit logrotate.timer).
Step 6: (Optional) Configure via systemd timer
In modern distributions, logrotate often runs via a systemd timer instead of cron. This allows more flexible scheduling.
- Check if the timer is active:
systemctl is-enabled logrotate.timer
Should returnenabled. - To change the run time (e.g., to 2:30 instead of 6:25), create an override:
sudo systemctl edit logrotate.timer
In the opened editor, add:[Timer] OnCalendar=daily Persistent=true RandomizedDelaySec=0
Or specify a concrete time:OnCalendar=*-*-* 02:30:00
Save and reload the daemon:sudo systemctl daemon-reload sudo systemctl restart logrotate.timer - For hourly rotation, create a separate timer or modify the config in
/etc/cron.hourly/(if the system uses cron). But remember: frequent rotation can burden the system if there are many logs.
Verification
After configuration, ensure rotation works reliably:
- Wait for the next cycle (if you tested with
-f, skip this) or run manually:sudo logrotate -vf /etc/logrotate.conf. - Check for archives: in the log directory, files with suffixes
.1,.1.gz(or.2, etc., depending onrotate) should appear. - Ensure new logs are written:
New entries should appear.tail -f /var/log/myapp/myapp.log - Monitor disk space:
The total size should not grow indefinitely.du -sh /var/log/myapp/ - Check that the service isn't crashing: if
postrotateincluded a reload, verify the application is running:systemctl status myapp.service
If all points are satisfied, rotation is configured correctly.
Common Issues
Permission Errors Accessing Log Files
Symptom: error: error opening /var/log/myapp/*.log: Permission denied.
Solution: Logrotate runs as root, but if logs belong to another user, ensure root has read access. Check ownership:
ls -la /var/log/myapp/
If needed, adjust permissions or add root to the owner's group.
Logs Not Rotating
Symptom: After logrotate -vf, nothing happens; files aren't moved.
Causes:
- File doesn't match the pattern (e.g.,
myapp.log.1instead ofmyapp.log). Clarify the path in the config. - File is empty and
notifemptyis set. Remove this option or create a test entry. - Rotation already happened recently (compare date in
/var/lib/logrotate/status). Forced run with-fshould help.
Compression Not Working
Symptom: Archives are created but without .gz.
Solution: Ensure gzip is installed (usually present). Check:
which gzip
If missing, install: sudo apt install gzip (Debian/Ubuntu) or sudo dnf install gzip (RHEL/Fedora).
Service Crashes After Rotation
Symptom: After rotation, the application stops writing logs or terminates.
Cause: The command in postrotate (e.g., systemctl reload) may fail if the service doesn't exist or requires a full restart.
Solution:
- Verify the service exists:
systemctl list-units | grep myapp. - Use
reloadonly if the service supports SIGHUP. Otherwise userestart. - Add
|| trueto the command to ignore errors (as in the example above).
Rotation Not Running on Schedule
Symptom: Status files aren't updated; no archives appear. Solution:
- For cron: ensure the
cronpackage is running (systemctl status cron), and that the script/etc/cron.daily/logrotateexists and is executable. - For systemd: check the
logrotate.timerand its status (systemctl list-timers | grep logrotate). The timer might be disabled — enable it:sudo systemctl enable --now logrotate.timer. - If you just configured the file, ensure it's syntactically correct (check with
logrotate -d).
Disk Still Fills Up
Symptom: Even after rotation, disk space isn't freed. Causes:
rotateis set too high (e.g.,rotate 365). Reduce it.- Compression is disabled (
compressmissing). Enable it. - Logs are written to other directories not covered by the config. Find all application logs:
find / -name "*.log" -path "*myapp*" 2>/dev/null. - The rotation process itself creates temporary files. Ensure there's enough space on disk for compression (temporary space needed for original + archive).
If the problem persists, add disk monitoring (e.g., via cron and df -h) and analyze which files are growing.