Logrotate and Disk Space Management on a VPS: Keep Logs Useful Without Filling the Disk

A full disk is one of the most common causes of VPS outages — and it is almost always self-inflicted. Application logs, database binlogs, and package manager caches grow silently until / hits 100%, at which point services start failing with cryptic No space left on device errors, SSH logins break, and even rm refuses to work for the root user in some configurations. The fix is a two-part routine: find what is consuming space, then rotate and prune logs automatically with logrotate and journald limits. This guide covers both, with configs you can copy straight onto a Debian or Ubuntu VPS.

The good news is that the tools are built into every Linux distribution — no extra agents or paid services required. If you are evaluating hosts for a workload that generates heavy logs, our comparison table includes plans with larger NVMe allocations, which gives you more headroom before rotation policies matter.

Step 1: Find What Is Eating the Disk

Start with filesystem usage, then drill down:

df -h                              # which mount is full
du -xh --max-depth=1 / | sort -h   # largest top-level directories
du -xh --max-depth=2 /var | sort -h | tail -10   # largest subdirs
find /var/log -type f -size +100M -exec ls -lh {} \;   # huge log files

On a typical web VPS, /var/log and /var/lib/docker are the usual suspects, followed by MySQL’s ib_logfile* and binary logs. The -x flag keeps du on one filesystem, so a large /proc or mount point does not skew the numbers.

Step 2: Logrotate — Rotation, Compression, Retention

Logrotate runs daily via cron and processes the configs in /etc/logrotate.d/ (plus the global defaults in /etc/logrotate.conf). The core directive set is small but powerful:

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14          # keep 14 rotated files
    compress           # gzip old logs
    delaycompress      # keep yesterday's log uncompressed
    missingok
    notifempty
    create 0640 www-data www-data
    postrotate
        systemctl reload myapp
    endscript
}

Two details matter in production. First, create restores the correct owner and permissions on the fresh log file so the app keeps writing after rotation. Second, the postrotate script tells the service to reopen its log handles — Nginx and Apache need reload or USR1; systemd services with StandardOutput=append: often need a restart instead. For services that reopen files on SIGHUP, use copytruncate instead: it copies and truncates without touching the file handle, at the cost of a few lost lines. When the log file is owned by a service user (common for PHP-FPM or containerized apps), add su www-data www-data to the config so rotation, compression, and create run as that user — otherwise logrotate may run as root and produce files the app cannot write to. If several services share one directory, wrap their postrotate scripts in sharedscripts so the reload runs once for the whole block rather than once per file. And if a service writes a high-volume log that must never grow beyond a fixed size regardless of time, replace daily with size 100M — rotation then triggers on file size instead of the clock.

Step 3: Cap journald Before It Caps Your Disk

systemd-journald writes its own binary journal under /var/log/journal and, left alone, can grow without bound. Set explicit size limits in /etc/systemd/journald.conf:

[Journal]
SystemMaxUse=500M        # cap the journal at 500 MB total
SystemMaxFileSize=100M   # individual file size before rotation
MaxRetentionSec=2week    # drop entries older than two weeks
Compress=yes

Apply with systemctl restart systemd-journald (or systemctl kill -s USR1 systemd-journald for a less disruptive reload). The journal will compact itself down to the new limit on the next rotation, freeing space without losing recent entries. A 500 MB cap plus two-week retention is a good default for most VPS workloads.

Step 4: Prune the Other Log Producers

  • Package caches: apt clean (or dnf clean all) after upgrades; keep apt‘s lists under control with apt-get autoclean.
  • Docker: add {"log-driver":"json-file","log-opts":{"max-size":"10m","max-file":"3"}} to /etc/docker/daemon.json, then docker system prune -af weekly for dangling images and build cache.
  • MySQL/MariaDB: set expire_logs_days=7 (or binlog_expire_logs_seconds=604800 on 8.0+) to prune binary logs automatically.
  • Old kernels: apt autoremove --purge removes superseded kernel packages that accumulate in /boot.

Step 5: Verify Rotation Works

Never trust a rotation policy you have not tested. Logrotate ships with a dry-run mode and a force flag:

logrotate -d /etc/logrotate.conf     # dry run: show what WOULD happen
logrotate -f /etc/logrotate.conf     # force rotation now
du -sh /var/log                      # confirm the directory shrank

Then add a simple disk-usage alert so you hear about the next slow leak before users do: a cron job that emails you when / passes 80%, or a one-line check in your existing monitoring script. Together with logrotate, journald caps, and the prune list above, that is a complete disk-space routine that runs itself.

Automating log rotation and disk monitoring is one of those admin tasks that quietly prevents the most embarrassing outage class there is. For the storage headroom that makes the whole system comfortable, see the full specs and pricing on plans with larger NVMe allocations.

Running these tools requires full shell access and cron control on an unmanaged server. InterServer’s VPS plans give you root access and flat pricing, so your log-rotation routine runs exactly as configured — no platform-level log managers getting in the way.

Leave a Reply