Technology

VPS Disk Usage and logrotate: Prevent “No Space Left on Device” Errors

On a busy VPS, disk space rarely disappears because of a single huge file. Most of the time, it is a slow and silent growth: web server access logs, PHP error logs, database logs, mail logs, application logs, temporary files and forgotten backups. One day a deploy fails, MySQL cannot write to its tables, or your site stops accepting uploads, all because of the classic “No space left on device” error. The good news is that this is one of the most predictable and preventable issues on a VPS. With a clear view of VPS disk usage and a correctly tuned logrotate configuration, you can keep your logs under control without breaking compliance rules or losing useful data.

In this article, we will look at how disk usage really behaves on a Linux VPS, how to diagnose what is filling the disk, how logrotate actually works, and which settings we use in production on dchost.com servers. We will finish with a practical checklist you can apply today to stop “No space left on device” errors before they reach your applications.

İçindekiler

How Disk Usage Really Works on a VPS

Before touching logrotate, you need a reliable mental model for how disk space is used and reported on your VPS. Otherwise, you will fix one directory and still be surprised by another mount point filling up.

Check overall disk usage with df

The first step is to see which filesystem is actually full:

df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   35G  3.8G  91% /
tmpfs           399M     0  399M   0% /run/user/0

Key points:

  • Use% above ~80–85% on root (/) is a warning sign; above 90% is serious.
  • On some setups, /var, /home, /tmp or /var/lib/mysql are on separate partitions; always check each mount point.

Do not forget inodes

Even with free GBs, you can hit “No space left on device” because you ran out of inodes (the metadata entries that track files). Check with:

df -i
Filesystem      Inodes  IUsed   IFree IUse% Mounted on
/dev/vda1      2621440 120000 2501440    5% /

If IUse% hits 100%, you have too many small files (often in cache or session directories). The fix is to clear or rotate these, not to grow the disk blindly.

Find which directories are heavy with du

Once you know which filesystem is full, use du to drill down:

cd /
sudo du -xh --max-depth=1 | sort -h

This shows which top-level directories are consuming space (for example /var, /home, /var/log, /var/lib). Then descend step by step:

cd /var
sudo du -xh --max-depth=1 | sort -h

On real dchost.com customer VPS setups, we often see most of the disk used by:

  • /var/log – web, PHP, database, mail and system logs
  • /var/lib/mysql or /var/lib/postgresql – databases and binary logs
  • /home/USER or /var/www – file uploads, backups, caches
  • /tmp or /var/tmp – session files, temporary uploads, uncleaned application temp files

Common Causes of “No Space Left on Device” on a VPS

Now that you know where to look, let us list the usual suspects we see during VPS audits and support tickets.

1. Log files that never rotate

This is by far the top reason. Even a medium-traffic site can generate:

  • Gigabytes of web server access logs (access.log)
  • PHP or application error logs when a bug spams the same stack trace
  • Mail server logs (maillog, exim, postfix logs)
  • Database error logs and slow query logs

If logrotate is misconfigured, or some custom log files are not included in /etc/logrotate.d/, a single file can reach tens of GB and push the filesystem over 100%.

2. Application caches and session files

Frameworks and CMSs (WordPress, Laravel, Magento, custom apps) often store cache and sessions in:

  • /var/www/example.com/storage/framework/cache (Laravel)
  • /var/lib/php/sessions (PHP sessions)
  • /tmp (generic temp files)

If you never purge these, millions of small files can accumulate. You might hit an inode limit before filling the disk in GB terms. Our separate article on Linux file permissions on shared hosting and VPS is also helpful here, because incorrect permissions sometimes prevent automated cleanups from running.

3. Backups and dumps stored on the same disk

A common pattern is a nightly mysqldump or tar of the full site stored in /home or /root without automatic pruning. After a few weeks, you have dozens of backups and no free space. For a deeper dive into realistic backup planning, look at our guide on how to design a backup strategy with RPO/RTO in mind.

4. Deleted but still-open log files

Even if you delete a huge log file, the space might not be freed if some process still has that file open. The disk remains full, and you still see “No space left on device”.

Find such files with:

sudo lsof | grep deleted

If you see large (deleted) files referenced by nginx, php-fpm, httpd or another daemon, you must restart that service so it releases the file handle.

5. systemd journal growing without limits

On modern distributions, systemd-journald stores logs in /var/log/journal. Without limits, it can grow to many gigabytes, especially on noisy systems. We will show how to configure safe limits in a later section.

Emergency Steps When the Disk Is Already Full

If your VPS is already returning “No space left on device”, you need a calm, step-by-step approach so you do not break databases or the OS while freeing space.

1. Confirm the situation

df -h

Identify which filesystem is 100% full. If only /boot or a small partition is full, the fix is different than when root (/) is full.

2. Locate large directories

Start with the full filesystem’s mount point:

cd /               # or /var, /home, etc.
sudo du -xh --max-depth=2 | sort -h | tail -n 20

This gives you the largest directories. Usually, /var/log or a backup directory stands out.

3. Safely trim obvious log bloat

When you identify an oversized log file (for example /var/log/nginx/access.log), you can truncate it instead of deleting it:

sudo truncate -s 0 /var/log/nginx/access.log

This keeps file ownership and permissions intact, which is safer than rm in production. For heavily used logs, consider:

  • Rotating them on the spot: sudo logrotate -f /etc/logrotate.d/nginx
  • Then confirming new compressed files have appeared and the active log file is small again

Warning: do not randomly delete directories like /var/lib/mysql, /var/lib/postgresql or /etc just to gain space. You will corrupt services and databases.

4. Remove old, local-only backups

If you find directories like /root/backups/ or /home/user/backup-YYYYMMDD.tar.gz, decide which ones are safe to remove. Ensure you have at least one recent, verified offsite backup before cleaning. If you are evaluating offsite options, our guide on offsite backups with restic/Borg to S3-compatible storage is a practical next step.

5. Restart services holding deleted files

If lsof | grep deleted reveals large deleted log files still referenced by daemons, restart only those services:

sudo systemctl restart nginx
sudo systemctl restart php-fpm

After that, confirm disk usage dropped with df -h. When the system is stable again, you can move on to permanent logrotate and journald tuning.

logrotate Basics: How It Keeps VPS Disk Usage Under Control

logrotate is the standard tool on most Linux distributions to automatically rotate, compress and prune log files. Understanding a few directives is enough to build robust configurations for a typical web VPS.

Where logrotate lives

  • Main config: /etc/logrotate.conf
  • Per-service configs: /etc/logrotate.d/ (for example nginx, apache2, mysql)

logrotate is usually triggered daily via cron or a systemd timer, which reads these configuration files and decides what to rotate.

Key logrotate directives in plain language

  • daily / weekly / monthly – how often to check and rotate the log.
  • size 100M – rotate logs when they reach or exceed 100 MB, even if the time-based period has not passed. Size-based rotation is very powerful to avoid “No space left on device” incidents.
  • rotate 14 – keep 14 rotated files (for example two weeks if rotating daily), then delete the oldest.
  • compress – compress old log files (usually with gzip) to save space.
  • delaycompress – start compressing from the second rotated file, leaving the most recent one uncompressed for tools that might still read it.
  • missingok – do not complain if the log file does not exist.
  • notifempty – do not rotate empty log files.
  • create 0640 www-data adm – after rotating, create a new log file with given permissions and owner/group.
  • copytruncate – copy the current log to a rotated file and truncate the original in place. Used for daemons that cannot be cleanly told to reopen log files.
  • dateext – append a date to rotated logs instead of just a numeric suffix.

Dry-run and force logrotate

Before applying new rules, test:

sudo logrotate -d /etc/logrotate.conf

The -d flag shows what logrotate would do, without touching files. To force a rotation (useful for testing or emergency cleanup):

sudo logrotate -f /etc/logrotate.conf

Practical logrotate Configurations for a Web VPS

Let us look at realistic example configurations for common services on a VPS: Nginx/Apache, PHP-FPM and MySQL/MariaDB. You can adapt the same patterns for your application logs.

Rotating Nginx logs safely

Create or edit /etc/logrotate.d/nginx:

/var/log/nginx/*.log {
    daily
    size 50M
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    create 0640 www-data adm
    postrotate
        [ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
    endscript
}

Why these options?

  • daily + size 50M – rotate at least once per day and earlier if a log grows too fast.
  • rotate 14 – about two weeks of logs; adjust for your compliance needs.
  • postrotate … kill -USR1 – tells Nginx to reopen log files gracefully without downtime.

Rotating Apache logs

On Apache-based servers, you will see something like this in /etc/logrotate.d/apache2 or /etc/logrotate.d/httpd:

/var/log/apache2/*.log {
    daily
    size 100M
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/sbin/apachectl graceful > /dev/null 2>&1 || true
    endscript
}

This gracefully reloads Apache after rotation so it writes to the new log files.

Rotating PHP-FPM error logs

PHP-FPM often logs to /var/log/php8.1-fpm.log (or similar). Example /etc/logrotate.d/php-fpm:

/var/log/php*-fpm.log {
    weekly
    size 50M
    rotate 8
    missingok
    notifempty
    compress
    delaycompress
    create 0640 www-data adm
    postrotate
        /usr/sbin/service php8.1-fpm reload > /dev/null 2>&1 || true
    endscript
}

You can change weekly to daily on high-traffic systems or during debugging phases where logs grow quickly.

Rotating application logs (Laravel, custom apps, etc.)

Many frameworks store logs under storage/logs or similar. You can create a generic rule:

/var/www/*/storage/logs/*.log {
    daily
    size 20M
    rotate 10
    missingok
    notifempty
    compress
    delaycompress
    copytruncate
}

Here we use copytruncate because application processes may not handle SIGUSR1 or SIGHUP-based log reopening nicely. copytruncate is slightly less safe for high-traffic logs but usually fine for application logs.

Rotating MySQL/MariaDB logs

MySQL has multiple types of logs: error log, slow query log and binary logs. Binary logs are usually managed by MySQL’s own configuration (expire_logs_days or binlog_expire_logs_seconds). For error and slow logs, logrotate is appropriate.

An example for the error log (/var/log/mysql/error.log):

/var/log/mysql/*.log {
    daily
    size 50M
    rotate 10
    missingok
    notifempty
    compress
    delaycompress
    create 0640 mysql adm
    sharedscripts
    postrotate
        test -x /usr/bin/mysqladmin || exit 0
        if [ -f /var/run/mysqld/mysqld.pid ]; then
           /usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs > /dev/null 2>&1 || true
        fi
    endscript
}

On heavily loaded ecommerce databases, you may also want to tune MySQL itself for fewer slow queries and less noisy logs. Our checklist on MySQL/InnoDB tuning for WooCommerce provides a practical roadmap.

Controlling systemd Journal Size (journald)

Even if all classic text logs are rotated, systemd-journald can still fill /var/log/journal if not limited. The journal is stored in a binary format and can grow quietly in the background.

Set journald limits

Edit (or create a drop-in) /etc/systemd/journald.conf and adjust these options:

[Journal]
SystemMaxUse=1G
SystemMaxFileSize=200M
MaxRetentionSec=1month

Explanation:

  • SystemMaxUse=1G – cap total journal size under 1 GB.
  • SystemMaxFileSize=200M – each individual journal file stays below 200 MB.
  • MaxRetentionSec=1month – keep at most one month of journal logs.

Then apply changes:

sudo systemctl restart systemd-journald

Clean up existing journal logs (with care)

To see journal disk usage:

journalctl --disk-usage

To vacuum old data while keeping at least 1 GB or 30 days of logs:

sudo journalctl --vacuum-size=1G
sudo journalctl --vacuum-time=30d

Always balance cleanup with compliance needs. If you operate in regulated environments (payment, healthcare, etc.), check your logging and retention obligations first. Our article on log retention on hosting and email infrastructure for KVKK/GDPR compliance is a useful reference.

Beyond logrotate: A Long-Term Strategy for VPS Disk Usage

Correct logrotate settings stop basic “No space left on device” errors, but healthy VPS disk usage also needs monitoring, smarter log storage and clear retention policies.

1. Set up monitoring and alerts

Do not wait for users to complain. At dchost.com, we strongly recommend:

  • Disk usage alerts when a filesystem passes 80% and 90%
  • Inode usage alerts above 70–80%
  • Log-specific alerts when error logs grow abnormally fast

If you want a hands-on example, our guide on VPS monitoring and alerts with Prometheus, Grafana and Uptime Kuma shows how to build a practical monitoring stack that includes disk space dashboards and alarms.

2. Consider centralised logging

On multi-VPS or growing environments, you may not want all logs to live on the same disk as your web application. Sending logs to a central logging stack keeps individual servers lighter and simplifies searching.

We have a step-by-step playbook on centralised VPS log management with Grafana Loki and Promtail that covers retention, indexing and alert rules. Offloading heavy logs like access logs and debug output to a dedicated logging VPS (or to object storage via a logging stack) is often cheaper than constantly upgrading your main VPS disk.

3. Separate critical data and logs on different partitions or servers

On higher-end setups, it is common to:

  • Keep /var/lib/mysql or other databases on their own fast disk or partition.
  • Place /var/log on a separate partition so a logging explosion cannot easily break the root filesystem.
  • Run dedicated database and application servers instead of everything on a single VPS.

If you are unsure when to separate database and application servers, you might find our article on when it makes sense to split database and application servers very helpful.

4. Align log rotation with compliance and forensics

It is tempting to set aggressive logrotate limits like rotate 3 and small sizes, but you may need logs for:

  • Security investigations (intrusions, fraud, abuse)
  • Compliance checks (PCI DSS, KVKK/GDPR, local regulations)
  • Debugging rare production issues

For ecommerce, for instance, our PCI-DSS compliant ecommerce hosting guide explains how to treat logs as security artefacts, not just noise. The usual pattern is:

  • Keep a shorter window (for example 7–30 days) on the VPS for quick debugging.
  • Ship compressed logs to a central, access-controlled location with longer retention.

5. Plan for growth and right-size your VPS

Even with perfect logrotate, no VPS disk is infinite. If your traffic or data grows, you will eventually need more space, better IOPS (NVMe) or a different architecture. When you are a dchost.com customer, our team can help you decide when to:

  • Increase VPS disk size or move to NVMe-based plans
  • Upgrade to a dedicated server for heavy databases or analytics workloads
  • Place your own hardware in our data center with colocation and attach larger storage

We also keep a practical guide to NVMe VPS hosting and real-world performance if you want to understand when faster disks really make a difference.

Step-by-Step Checklist to Prevent “No Space Left on Device” on Your VPS

To turn all this into concrete action, here is a concise checklist you can apply to any Linux VPS.

One-time baseline

  1. Inventory your filesystems: run df -h and note all mount points and their sizes.
  2. Map current usage: use du -xh --max-depth=2 under /, /var, /home, and /var/lib to find heavy directories.
  3. Review existing logrotate configs: inspect /etc/logrotate.conf and /etc/logrotate.d/*. Ensure all major logs (web, PHP, database, mail, app) are covered.
  4. Set journald limits: configure SystemMaxUse, SystemMaxFileSize and MaxRetentionSec in /etc/systemd/journald.conf.
  5. Document retention needs: decide how long you need logs for operations vs. compliance, and whether you will use centralised logging.

logrotate hardening

  1. Add size-based limits (for example size 50M or size 100M) to busy logs.
  2. Set reasonable rotate counts (for example 7–30) based on how often you rotate and how long you keep on the VPS.
  3. Enable compression for older logs and delaycompress where your tools expect a plain-text recent file.
  4. Use create/copytruncate correctly: use create with proper permissions for system daemons, copytruncate for stubborn app logs.
  5. Test changes with logrotate -d (dry-run) and then logrotate -f for one-off verification.

Ongoing maintenance

  1. Monitor disk and inode usage: add alerts for >80–90% usage.
  2. Regularly inspect heavy directories: monthly reviews of /var/log, /var/tmp, application cache and backup locations.
  3. Keep backup storage separate: avoid stacking many full-site backups on the same disk as your live app.
  4. Review logs for anomalies: sudden growth often indicates bugs or attacks that also deserve security attention.

Conclusion: Keep VPS Disk Usage Predictable and Boring

“No space left on device” is one of those errors that should only happen once on any VPS. After the first incident, you know where to look and what to fix: oversized logs, unbounded systemd journals, forgotten backups and chatty applications. With a clear view of VPS disk usage, carefully tuned logrotate rules and a few journald limits, disk space becomes predictable instead of a surprise.

At dchost.com, we design our VPS, dedicated server and colocation environments with these practices in mind. When you host with us, our team can help you review your logging setup, tune logrotate for your specific stack (WordPress, Laravel, Node.js, ecommerce platforms and more), and implement monitoring so you see disk issues long before they affect users. If you are planning a new project or migrating an existing one, this is also a great moment to revisit your backup and logging strategy in parallel with your hosting choice.

If you want a calm, no-drama VPS experience, start by applying the checklist above on your current server. And if you prefer to do this together, reach out to our support team at dchost.com – we are happy to help you keep your disks clean, your logs useful and your applications far away from “No space left on device” errors.

Frequently Asked Questions

This situation usually happens for two reasons: inode exhaustion or deleted-but-open files. If you run df -i and see IUse% at 100%, it means you have created so many small files (often in cache or session directories) that the filesystem ran out of inodes, even though it still has free GBs. Alternatively, you may have deleted a huge log file while a service like nginx or php-fpm still has it open. In that case, the space is not actually freed until the process is restarted. Use lsof | grep deleted to find such files, restart the relevant service, and then review logrotate and application cache settings so the problem does not return.

There is no single answer, but a good baseline for most web VPS setups is daily rotation with a size limit. For busy logs like web server access and PHP error logs, use daily plus size 50M or size 100M and keep 7–30 rotated files depending on your retention needs. For quieter logs, weekly rotation can be enough. The key is combining time-based (daily/weekly) and size-based (size 50M) rules so logs cannot grow beyond a safe limit between rotations. Always enable compression for older logs, and adjust rotate counts to match your operational and compliance requirements.

Use create when the service can reopen its log files cleanly after rotation, usually via a postrotate script that sends a signal or reload (for example, nginx with kill -USR1, Apache with apachectl graceful). create removes the old file, creates a new one with defined permissions, and lets the daemon start writing to it. copytruncate is a workaround for applications that do not handle log reopening well; it copies the current log to a rotated file and truncates the original in place. This is simpler for custom apps but slightly less safe under very high write rates, because a few log lines can be lost during the copy-and-truncate window.

Edit /etc/systemd/journald.conf and set explicit limits under the [Journal] section, such as SystemMaxUse=1G, SystemMaxFileSize=200M and MaxRetentionSec=1month. These options cap the total size, the size of each journal file and the maximum retention window. After changing the file, run systemctl restart systemd-journald to apply the new settings. You can check current usage with journalctl --disk-usage and, if necessary, clean older data with journalctl --vacuum-size=1G or --vacuum-time=30d. Always ensure that your new limits still meet your operational and compliance requirements for log retention.

The safest approach is to avoid stacking many full-site backups on the same disk as your live application. Instead, keep a small number of short-term local backups for quick restores and send regular encrypted backups to external storage, such as S3-compatible object storage or a separate backup VPS. Use tools like restic, Borg, rclone or rsync over SSH with retention policies that automatically prune old backups. This way, you protect yourself against both data loss and disk-full incidents. Pair this with regular restore tests and a clear RPO/RTO plan, as discussed in our backup strategy guides, so you know exactly how much data you can afford to lose and how quickly you can recover.