Log Rotation and Disk Space Management on Linux

Khimananda Oli 7 min read Database
Log Rotation and Disk Space Management on Linux

By Khimananda Oli | Last reviewed: August 2026

Uncontrolled log growth is one of the most common causes of avoidable production outages I see across both global and Nepali infrastructure teams. Effective log rotation and disk space management on Linux prevents "No space left on device" errors that crash databases and web servers at peak traffic. This guide provides the exact configuration patterns, cleanup routines, and monitoring hooks you need to keep systems stable without losing critical audit data.

How Do You Configure Logrotate for Production Applications?

The logrotate utility is the standard mechanism for log rotation and disk space management on Linux. While default OS logs are handled automatically, application logs from Nginx, Laravel, Docker, or custom services require explicit configuration. A common mistake is relying solely on time-based rotation; in high-traffic environments, size-based triggers are essential to prevent partition overflow between scheduled runs.

Active App Logsize/timeRotate & RenameCompress (.gz)Delete (retain N)Log Rotation LifecycleEnsures predictable disk usage and compliance-ready retention
Log rotation lifecycle: active logs transition through rename, compress, and delete stages to maintain safe disk utilization.

Create an Application-Specific Rotation Policy

Place custom configurations in /etc/logrotate.d/ rather than editing the main logrotate.conf. This keeps your rules modular and version-controllable — a practice I enforce when setting up Laravel deployments on Ubuntu VPS.

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 30
    size 100M
    missingok
    notifempty
    compress
    delaycompress
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}
  • size + daily: Rotates if either threshold is met first, covering both burst traffic and quiet periods.
  • delaycompress: Keeps the most recent rotated file uncompressed so debugging tools can read it without decompression.
  • create: Ensures the new log file has correct ownership immediately; without this, applications may fail to write after rotation.
  • postrotate: Signals the application to reopen file handles. Omitting this is the #1 cause of "logs not rotating" complaints.

Validate Configuration Before Deploying

Always test with debug mode to catch syntax errors or permission issues without modifying actual files:

sudo logrotate -d /etc/logrotate.d/myapp

Force a manual rotation during maintenance windows to verify the full cycle works under real conditions:

sudo logrotate -f /etc/logrotate.d/myapp

What Commands Diagnose Disk Space Issues Accurately?

When alerts fire, you need precise diagnostics fast. df -h shows filesystem-level usage but hides inode exhaustion and per-directory bloat. Pair it with these targeted commands for complete visibility during incident response.

# Find directories consuming most space under /var/log
sudo du -ahx /var/log | sort -rh | head -20

# Check inode usage (critical for mail queues, cache dirs)
df -i /var

# Identify deleted-but-open files holding space
sudo lsof +L1 | grep deleted

# List files larger than 500MB modified in last 7 days
find /var/log -type f -size +500M -mtime -7 -exec ls -lh {} \;

The lsof +L1 command deserves special attention. When a process deletes a log file but keeps it open, the space remains allocated until the process closes the handle or restarts. This phantom usage confuses many engineers who see du reporting low usage while df shows 98% full. Truncating the file descriptor (: > /proc/PID/fd/FD) reclaims space without restarting the service.

Automate Diagnostics with Cron

Schedule lightweight checks that report anomalies before they become emergencies. I use this pattern on every managed server:

# /etc/cron.d/disk-health-check
*/15 * * * * root /usr/local/bin/check-disk.sh | logger -t disk-monitor

Pair automated checks with structured observability. If you're running Prometheus and Grafana for monitoring, expose disk metrics via node_exporter and set alerts at 80% warning / 90% critical thresholds.

How Do You Balance Retention Requirements Against Storage Costs?

Retention isn't purely technical — it's governed by compliance, forensics, and cost. SOC 2 and ISO 27001 audits typically require 12-month log availability, but keeping everything on primary storage is wasteful. Tier your approach based on access patterns.

TierDurationStorage LocationUse Case
Hot7–30 daysLocal SSD/NVMeActive debugging, real-time alerting
Warm30–180 daysObject Storage (S3/B2)Audit queries, trend analysis
Cold1–7 yearsGlacier/Archive TierCompliance, legal holds, forensics
Hot (Local)7–30d • Fast AccessarchiveWarm (Object)30–180d • Audit ReadylifecycleCold (Archive)1–7yr • ComplianceAutomated Sync Script / S3 Lifecycle PolicyMoves compressed logs nightly • Deletes local copies after upload verified
Tiered retention architecture balances fast access, audit readiness, and long-term compliance cost-effectively.

Implement Automated Offloading

Use a simple script triggered by postrotate or a dedicated cron job to push compressed logs to object storage. Verify uploads before deleting local copies to prevent data loss:

#!/bin/bash
# /usr/local/bin/offload-logs.sh
BUCKET="s3://company-logs-archive"
LOCAL_DIR="/var/log/myapp/archive"

aws s3 sync "$LOCAL_DIR" "$BUCKET" --only-show-errors
if [ $? -eq 0 ]; then
    find "$LOCAL_DIR" -name "*.gz" -mtime +7 -delete
    echo "$(date): Offload complete" >> /var/log/offload.log
else
    echo "$(date): OFFLOAD FAILED - local files retained" >> /var/log/offload.log
    exit 1
fi

This tiered model directly supports cloud cost optimization by moving bulk storage to cheaper tiers while keeping recent data locally accessible.

When Should You Use Journald vs Traditional Log Files?

Modern systemd-based distributions default to journald, which offers structured metadata and binary indexing. However, traditional plaintext files remain preferable for many production workloads due to tooling compatibility and predictable rotation behavior.

CriteriajournaldTraditional Files
Rotation ControlSize/vacuum onlyFull logrotate flexibility
External Tool SupportRequires exportNative grep/awk/sed
Persistence DefaultVolatile (RAM)Disk by default
Centralized ShippingNeeds forwarderDirect file tailers
Disk PredictabilityLess intuitive limitsExplicit size caps

In practice, I configure journald for system services but route application output to dedicated files. Edit /etc/systemd/journald.conf to enforce sane defaults:

[Journal]
SystemMaxUse=2G
SystemKeepFree=4G
MaxRetentionSec=30day
ForwardToSyslog=no

For applications where plaintext logs are mandatory (e.g., PCI-DSS environments requiring direct file integrity monitoring), disable journald forwarding entirely and rely on logrotate as the single source of truth for log rotation and disk space management on Linux.

How Do You Prevent Common Rotation Failures Silently?

Configuration drift and silent failures undermine even well-designed rotation policies. These three checks should be part of your baseline hardening, similar to the steps covered in initial Ubuntu server setup.

  1. Verify cron execution: Confirm /etc/cron.daily/logrotate exists and is executable. On minimal containers, cron may not be installed — add it explicitly or use systemd timers.
  2. Monitor rotation success: Parse /var/lib/logrotate/status to detect stale entries. Alert if any configured log hasn't rotated within expected intervals.
  3. Test permissions post-rotation: Include an assertion in your deployment pipeline that validates new log files have correct ownership after forced rotation. Permission bugs often surface only after the first production rotation.
Log Not Rotating?Run: logrotate -d /etc/logrotate.d/appSyntax ErrorConfig OKFix Config SyntaxCheck paths, braces, directivesCheck Permissions & Cronls -la /etc/cron.daily/logrotateVerify postrotate SignalApp must reopen file handles
Troubleshooting flowchart: systematic diagnosis of log rotation failures from syntax to runtime signals.

Conclusion

Reliable log rotation and disk space management on Linux combines disciplined configuration, tiered retention, and proactive monitoring. Start by auditing your current /etc/logrotate.d/ policies against the patterns above, implement size-based triggers alongside time schedules, and establish automated offloading to object storage within 30 days. Document your retention tiers explicitly — auditors and future engineers will thank you. If your team needs help designing compliant, cost-efficient logging infrastructure, reach out to discuss your specific requirements.

Frequently Asked Questions

Logrotate is the standard utility for automating log file management on Linux systems. It prevents disk exhaustion by rotating, compressing, and removing old logs based on size or time policies, ensuring applications continue writing without interruption while maintaining manageable archive sizes for debugging and compliance auditing.

Edit or create a config file in /etc/logrotate.d/ specifying the target log path. Add the size directive followed by your threshold, such as size 100M. Logrotate checks this condition during its daily cron execution and rotates the file only when it exceeds the specified byte limit.

Yes. Create separate configuration blocks within individual files under /etc/logrotate.d/. Each block defines specific paths and directives like rotate, compress, and postrotate scripts independently, allowing distinct retention schedules and compression settings for application logs, system journals, and database outputs on the same server.

Logrotate skips the file and logs an error to syslog. Use copytruncate to safely rotate active files without restarting services, or configure a postrotate script to signal the application to reopen file descriptors. Always test configurations with logrotate -d first to verify permissions and locking behavior before deployment.

Systemd journal manages its own binary logs independently of logrotate via journald.conf settings like SystemMaxUse. Traditional logrotate only handles text files in /var/log. Mixing both requires understanding that journal vacuuming and logrotate operate on separate storage pools with distinct retention mechanisms and disk space accounting methods.

No. Deleting open files does not free disk space until the process closes the descriptor. Use truncate -s 0 logfile or logrotate with copytruncate to safely reclaim space. Manual deletion risks data loss and leaves phantom inodes consuming storage until service restart, defeating immediate recovery efforts during incidents.

Run logrotate -d /etc/logrotate.d/your-config to perform a dry run. This verbose debug mode shows exactly which files would rotate, what commands execute, and any permission errors without modifying actual logs. Always validate syntax and path resolution this way before deploying changes to production environments.

Check /var/lib/logrotate/status for stale state files, verify cron.daily execution via systemctl status cron, and inspect /var/log/syslog for parse errors. Misconfigured paths, missing include directives in logrotate.conf, or AppArmor denials frequently cause silent failures. Test manually with logrotate -f to isolate scheduling versus configuration issues.

Use df -h combined with du -sh /var/log/* in scheduled monitoring checks. Tools like Prometheus node_exporter expose filesystem metrics for alerting. Analyze growth patterns over weeks to set appropriate size thresholds rather than arbitrary defaults, balancing retention needs against available storage capacity and ingestion rates.

Minimal impact occurs because compression runs after rotation during low-activity windows. Use delaycompress to defer compression one cycle, avoiding CPU contention during peak writes. Modern gzip and zstd complete typical log compression in seconds. Monitor load averages if processing multi-gigabyte files, but overhead is generally negligible for standard workloads.

Implement tiered retention using logrotate with monthly rotation and yearly archival to object storage via postrotate scripts. Keep recent logs locally for operations while offloading older archives to S3 or GCS. Configure lifecycle policies on cloud storage for automatic deletion after compliance periods expire, separating operational access from regulatory requirements.

Config files must be owned by root with mode 0644. Logrotate refuses to process world-writable or group-writable configs to prevent privilege escalation attacks. Ensure log directories themselves restrict write access appropriately. Audit /etc/logrotate.d/ regularly for unauthorized modifications that could inject malicious postrotate commands executed with root privileges during rotation cycles.

Not natively. Pair logrotate with external monitoring via mailx in postrotate scripts or use systemd timers with OnFailure handlers. Better yet, integrate filesystem alerts through Prometheus or Datadog watching /var/log partition usage. Relying solely on logrotate for failure notification creates blind spots since it cannot report its own execution failures reliably.

Containers should write to stdout/stderr, letting the container runtime handle rotation via daemon.json max-size and max-file settings. Avoid mounting host logrotate into pods. For sidecar logging agents, configure Fluent Bit or Vector with buffer limits and backpressure handling instead of relying on filesystem-level rotation inside ephemeral containers.

Dateext appends YYYYMMDD timestamps to rotated filenames instead of sequential .1 .2 suffixes. This simplifies identifying logs by date without checking modification times and prevents name collisions during manual interventions. Enable globally in logrotate.conf or per-block. Combine with dateformat -%Y%m%d-%H%M%S for hourly rotations requiring finer granularity than daily defaults provide.