HYEHOST

Linux Disk Full? Fix “No Space Left on Device” on a VPS

Fix Linux “No space left on device” errors with disk, inode and Docker checks. Find large files, control logs and recover VPS space without deleting needed data.

Start the disk checksExplore backup storage
HYEHOST bear mascot diagnosing a full Linux disk with storage usage gauges

A bot stops saving state. A database refuses a write. A Docker deployment fails halfway through an image pull. They can all produce a “No space left on device” error, but buying a bigger virtual disk is not always the right first response.

If this is a production incident, pause nonessential imports, builds and backup jobs that are still generating data. Keep your current administrative session open and confirm you have panel console access. Avoid an unplanned reboot: a server with no working space may fail to bring its applications back online.

1. Identify which filesystem is actually full

Run these checks over SSH or through your VPS console:

df -hT
df -i
lsblk -f

df -hT shows filesystem capacity and type; df -i shows inode usage. The Mounted on column matters as much as the percentage. A full /var is a different problem from a full /boot, even when both belong to the same VPS. See the GNU df manual.

Check the exact directory mentioned in the error. This example checks /var; substitute an existing directory where your application writes:

df -hT /var
df -i /var
findmnt -T /var
What you findLikely directionNext check
Almost no available bytesFiles or filesystem data consume the spaceInspect directory sizes
Inodes at or near 100%Too many filesystem objectsFind directories with many small files
df is much larger than duOpen deleted files, hidden data or filesystem accountingInspect open files and mounts
Root has room, another mount is fullThe application writes somewhere elseFollow the exact failing path
A tmpfs mount is fullTemporary memory-backed storage is exhaustedInspect that mount and its producer

If the error is “Disk quota exceeded”, investigate the account or project quota too. If it is “Read-only file system”, investigate mount state and kernel errors instead of assuming ordinary capacity exhaustion. Do not force a damaged filesystem writable to make the message disappear.

2. Find large directories without crossing other filesystems

Start broad, then inspect one level deeper. These commands report usage without removing anything:

sudo du -xhd1 / 2>/dev/null
sudo du -xhd1 /var 2>/dev/null
sudo du -xhd1 /var/log 2>/dev/null

GNU du's -x stays on the starting filesystem and -d1 limits the displayed depth. Scan a separate data mount explicitly if that is the full filesystem. The error redirection hides warnings, so rerun without it if a result looks incomplete. A deep scan can still create substantial disk I/O. See the GNU du manual.

Common suspects include application uploads, database directories, old backup archives and container storage. Finding a large database directory is not permission to delete its contents: tables, transaction logs and recovery files belong to the database's own lifecycle.

Look for an explanation, not just a large number. A 40 GB media library may be expected; a log growing several gigabytes an hour is not. Compare application activity with the point when disk usage changed. Avoid installing extra diagnostic packages while the root filesystem has no room to unpack them.

3. Check for inode exhaustion and small-file growth

On filesystems with a finite inode pool, a huge number of small files can prevent new files being created even when there are free gigabytes. Cache directories, session files and abandoned job outputs are useful places to investigate.

sudo du --inodes -x -d1 /var 2>/dev/null

Follow the largest count into the relevant directory. For example, if an application's session cache is responsible, check its configured expiry and garbage collection. Use that application's supported cleanup process rather than recursively deleting a system directory.

Correct the producer as well as the backlog. Otherwise a cleanup merely resets the countdown to the next incident. Keep enough representative information to understand why the files accumulated, but do not copy millions of files to another directory on the same full filesystem. That does not create capacity.

4. Find deleted files that still occupy disk space

Removing a directory entry does not necessarily release its blocks immediately. A process may still hold the file open. If lsof is already installed, inspect files with no remaining links:

sudo lsof +L1

Check the command, PID, size and filename. Coordinate a supported log reopen, reload or restart of the owning service; the space is normally released once the final reference closes. Do not kill a database process or truncate a file descriptor just because it appears in this list. The lsof manual documents the link-count selection.

A disagreement between df and du is a clue, not proof of this cause. Filesystem metadata, reserved capacity, snapshots and files hidden underneath a mount can also affect the totals. A backup job can accidentally write into a local mountpoint when its remote filesystem is absent. Check mount state before starting the next backup; do not unmount a busy production filesystem simply to look underneath it.

5. Recover space from logs and package caches deliberately

System journal: inspect before reducing history

sudo journalctl --disk-usage

If the journal is a significant contributor, preserve any logs needed for incident investigation or retention requirements first. The following example deletes older archived journal history to work towards a 500 MB size limit; choose a policy appropriate to your service:

sudo journalctl --rotate --vacuum-size=500M
sudo journalctl --disk-usage

Vacuuming acts on archived journal files, not active ones. Rotation makes the current files eligible, but the final total is not guaranteed to equal the requested size. This is a one-time cleanup, not a permanent retention policy. Configure journald limits separately if needed. See the systemd journalctl manual.

APT cache: remove downloaded packages, not installed software

On Debian and Ubuntu, first see whether the download cache is worth clearing:

sudo du -sh /var/cache/apt/archives

If you do not need the cached installers for offline recovery, this removes downloaded package archives:

sudo apt-get clean

It does not uninstall your applications. It also cannot reclaim files that were never in that cache. Do not substitute a blanket package-removal command. The APT manual distinguishes cache cleaning from removing packages.

Application logs: use the configured rotation mechanism

For web servers, bots and custom services, identify the log destination and its rotation policy. Preserve evidence before shortening retention. A noisy error loop should be fixed at source; keeping only a tiny history can conceal a recurring fault without solving it.

6. Investigate Docker disk usage and stop runaway logs

On a Docker host, separate images, writable container layers, volumes and build cache before choosing any cleanup:

sudo docker system df -v
sudo docker ps -a --size
sudo docker info --format '{{.DockerRootDir}}'

docker system df reports Docker's object usage, not every byte consumed anywhere on the host. Bind-mounted application data and log storage need separate attention. Inspect the data root reported by your own daemon rather than assuming every installation uses the same path.

For each growing service, inspect its current logging configuration. Replace CONTAINER_NAME with the actual name:

sudo docker inspect --format '{{json .HostConfig.LogConfig}}' CONTAINER_NAME

Docker's local logging driver rotates logs and can use explicit limits. Merge this fragment into the relevant service in your existing Compose file; it is not a complete application definition:

services:
  app:
    # Keep your existing image, volumes, networks and other settings.
    logging:
      driver: local
      options:
        max-size: "10m"
        max-file: "3"

This bounds the retained stdout/stderr logs for that container, not logs the application writes into a bind mount or volume. Check compatibility with any log collector before changing drivers. Use application-specific retention for file-based logs too.

After confirming persistent data is stored outside the container's writable layer and you have recoverable backups, apply the change during a maintenance window. Replace app with the real Compose service name:

sudo docker compose config --quiet
sudo docker compose up -d --no-deps --force-recreate app

Recreation interrupts that service and replaces its writable layer. A simple restart does not change the container's logging configuration. Recheck the configuration and health afterwards. Do not manually delete or truncate Docker-managed log files; see the local logging driver documentation and Compose logging reference.

7. Prevent the next full disk

After each controlled change, rerun the checks against the affected filesystem and verify that the application can save data again. Do not declare the incident resolved simply because the percentage dropped. Test the failed operation, inspect service health and confirm scheduled jobs are no longer immediately filling the reclaimed space.

  • Monitor every relevant mount: root, application data and backup destinations, plus inode usage where applicable.
  • Alert with headroom: use both free capacity and growth rate. An example 80% warning and 90% critical threshold should be adjusted to your disk size, write rate and response time.
  • Bound retention: set policies for logs, uploads, build artifacts and backups separately.
  • Test missing-mount handling: a backup should fail visibly if its intended destination is unavailable.
  • Keep recovery copies elsewhere: a backup on the same disk competes with production and shares its failure risks.

Our Beszel monitoring guide is a useful starting point for visibility across your servers. Pair monitoring with ownership: someone needs to receive the alert and know which cleanup procedure is safe.

8. When to add storage, and where HYEHOST fits

Once growth is understood, extra capacity may be the correct answer. A genuine growing dataset is different from an unbounded debug log. Keep working space for upgrades, database maintenance and temporary files rather than planning to run permanently at the limit.

RequirementHYEHOST optionImportant distinction
Linux applications with root controlCloud VPSManage your OS, logging and application retention
Off-server backup filesStorage BoxManaged remote storage, not an automatic extension of your root disk
A self-managed backup server or large archive VMStorage VPSRoot-access KVM with capacity-focused HDD data storage

Use a Storage Box with a supported backup client such as rclone over SFTP, or compare Restic, BorgBackup and Kopia. Upload, verify and test restoring before removing local recovery copies. Never move live database files to a remote file mount as an improvised space fix; use application-consistent backups or a planned migration.

Increasing a virtual disk allocation may still require guest partition, logical-volume or filesystem expansion. The correct procedure depends on your layout. Check lsblk -f, keep a backup and follow a layout-specific procedure instead of copying a generic resize command intended for another filesystem.

Disk-full recovery checklist

  • The failing path and filesystem are identified.
  • Both free bytes and inode usage have been checked.
  • The data producer is understood and unnecessary growth is paused.
  • Important data and required log history are protected before cleanup.
  • Only a reviewed cleanup or retention change has been applied.
  • Applications can write again and restarted services are healthy.
  • Monitoring and retention are in place before normal jobs resume.
  • Backups are independent and a restore has been tested.

Linux disk-full FAQs

Why does Linux say no space left on device when space is available?

The affected filesystem may have run out of inodes rather than bytes, or the application may be writing to a different mount, a full temporary filesystem or a container layer. Check the exact failing path with df -hT and df -i. Quotas and filesystem-specific limits may also need investigation.

Why is disk space still used after deleting a file?

A process can keep a deleted file open. The storage is normally released when its final open reference is closed. Use sudo lsof +L1 to identify candidates, then plan a supported reload or restart of the owning service.

Is docker system prune safe for a production VPS?

Not as a blind first step. It can remove stopped containers, unused networks, images and build cache. Adding volume-pruning options increases the risk of losing persistent data. Inspect usage and remove only objects you have confirmed are no longer needed.

Does adding more VPS storage fix inode exhaustion?

Not automatically. It depends on the filesystem and how it is expanded. Find the source of excessive small files, correct its retention policy and verify inode capacity after any storage change.

Should I use a Storage Box or a Storage VPS for backups?

A Storage Box suits managed remote file storage accessed with tools such as SFTP, rsync or backup clients. A Storage VPS provides a Linux VM with root access for a self-managed backup service. Neither replaces retention rules, encryption or restore testing.