
A VPS rarely creeps toward “disk full.” It usually hits a wall.
WordPress uploads fail. MySQL starts throwing errors. Mail queues back up, and your control panel times out.
This disk space troubleshooting tutorial shows you how to confirm what’s actually full (blocks vs. inodes), find the real source of usage, clean up safely, and add guardrails so you don’t repeat the outage.
The examples use Ubuntu/Debian with systemd. The same diagnostics work on AlmaLinux/Rocky.
Every command below is meant to be copy/paste-friendly. The cleanup steps focus on low-risk changes.
Before you touch anything: take 3 minutes to avoid making it worse
- Open a second SSH session before changing anything. If one shell locks up, you still have a way in. If SSH is unstable, use this guide: VPS SSH timeout troubleshooting.
- Confirm you’re on the right server (this goes wrong more often than people admit):
hostnamectlandip a. - Stop the “space amplifier” first. If a service is spewing logs or a backup job is looping, pause that service. Don’t start deleting until the writing stops.
If this is a production store or client workload, consider testing cleanup steps on a staging clone first.
If you’d rather not handle disk incidents yourself, managed VPS hosting is designed for this kind of operations work.
Step 1 — Prove what’s actually full: blocks or inodes
Two different problems can look identical from the application side:
- Blocks full (real disk usage): the filesystem is out of free bytes.
- Inodes full: you still have free bytes, but you’ve hit the file-count limit (common with caches, spools, and tiny session files).
df -hT
Find the mount at 100% (often / or /var).
Then check inodes:
df -ih
Decision point:
- If
Use%is 100% indf -h, you’re on the “blocks” path below. - If
IUse%is 100% indf -ih, skip ahead to the inode section.
Step 2 — Find the biggest directories fast (without guesswork)
Start at the filesystem root. Don’t cross into other mounts.
This stays quick and predictable:
sudo du -xhd1 / 2>/dev/null | sort -h
Next, drill into whichever directory comes back largest (often /var or /home):
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo du -xhd1 /home 2>/dev/null | sort -h
If du is crawling, check the usual hotspots first:
/var/log(logs)/var/lib(databases, Docker, packages)/var/spool(mail queues, print spools)/home/*/public_html(backups, cache, media)
Step 3 — Common cause #1: logs that grew out of control
One noisy service can fill a disk fast.
Start by listing the biggest log files:
sudo find /var/log -type f -printf '%s %p\n' 2>/dev/null | sort -n | tail -30
On systemd hosts, the journal can also get huge:
sudo journalctl --disk-usage
Safe cleanup options (pick one):
- Vacuum the journal to a fixed size:
sudo journalctl --vacuum-size=1G - Vacuum by time (useful if you only need recent logs):
sudo journalctl --vacuum-time=7d
For plain files in /var/log, don’t start with rm if the service is still writing.
Truncate instead. That way, the process keeps its file handle:
sudo truncate -s 0 /var/log/nginx/access.log
sudo truncate -s 0 /var/log/nginx/error.log
Pitfall: deleting an open log file often doesn’t free space until the service restarts.
To confirm, list deleted-but-open files:
sudo lsof +L1 | head -100
If you see large entries marked (deleted), restart only the service holding the file.
Do it during a quieter window when possible:
sudo systemctl restart nginx
Once you’re out of the emergency, set proper rotation and retention so this doesn’t come back. Use: VPS log rotation tutorial.
Step 4 — Common cause #2: backups stored on the same disk (and never pruned)
Backups don’t belong only on the server you’re backing up.
Local snapshots help with quick rollbacks. They won’t save you from a dead disk or a compromised VPS.
During a disk incident, you’ll often discover years of tarballs in /home or /root.
Search for common backup patterns:
sudo find /home /root -maxdepth 3 -type f \( -name '*.tar' -o -name '*.tar.gz' -o -name '*.tgz' -o -name '*.zip' -o -name '*.sql' -o -name '*.gz' \) -printf '%s %p\n' 2>/dev/null | sort -n | tail -40
Safe cleanup checklist:
- Keep the most recent known-good backup until the server is stable.
- Move older backups to object storage or another VPS, then delete the local copies.
- Afterward, add prune jobs (daily/weekly) so the directory can’t grow forever.
If you already have offsite backups, confirm you can actually restore them.
If you can’t restore it, it’s not a backup—it’s just disk usage. This pairs well with: VPS backup verification tutorial.
Step 5 — Common cause #3: Docker and container image buildup
Even if you didn’t install Docker intentionally, plenty of stacks rely on it.
Old images, stopped containers, and unused volumes accumulate quietly.
Start with Docker’s own view of disk usage:
docker system df
Safe reclaim path: remove only unused data (dangling images, stopped containers, unused networks).
Add --volumes only if you’re sure what lives in volumes.
docker system prune
If you’re confident unused volumes aren’t holding anything you care about (common on dev VPSes), run:
docker system prune --volumes
Pitfall: pruning volumes can remove persistent data (uploads, database files) if you stored them in Docker volumes.
If there’s any doubt, inspect first:
docker volume ls
docker volume inspect <volume_name>
Step 6 — Common cause #4: email spools and queues (especially on hosting servers)
Mail servers don’t degrade gracefully under disk pressure.
Once queues start backing up, disk usage accelerates. Deliverability usually drops with it.
Quick checks:
- Exim queue size (common on cPanel/WHM):
exim -bpc - Postfix queue size:
postqueue -p | tail -n 1 - Mail spool growth:
sudo du -sh /var/spool/* 2>/dev/null
If you run WHM, treat mail queues like an incident, not housekeeping.
This guide matches that workflow: cPanel Mail Queue Tutorial (2026).
A fix that doesn’t involve deleting mail: stop the spam burst at the source (compromised account, exploited script, or a bad PHP mailer).
Then let the queue drain normally. Blind deletes tend to wipe real mail along with the junk.
Step 7 — The silent killer: inode exhaustion (millions of tiny files)
If you’re out of inodes, deleting one 10GB file won’t move the needle.
You need to remove lots of small files.
Start by checking file counts in common trees. This can take a while on large filesystems:
sudo bash -lc 'for d in /var /tmp /home; do echo "### $d"; find "$d" -xdev -type f 2>/dev/null | wc -l; done'
After you find the worst offender, drill down from there.
/tmp and application caches are frequent sources.
On WordPress, plugin cache directories and image-optimizer temp folders are repeat offenders.
Practical inode cleanup targets (verify before deleting):
/tmpand/var/tmpstale files (older than 7 days):sudo find /tmp -xdev -type f -mtime +7 -delete sudo find /var/tmp -xdev -type f -mtime +7 -delete- Session files (PHP sessions can pile up). On Debian/Ubuntu:
sudo ls -lah /var/lib/php/sessions | head sudo find /var/lib/php/sessions -type f -mtime +2 -delete
Pitfall: don’t purge actively used sessions during peak traffic on busy eCommerce sites.
It usually won’t “break” the site. It can log users out and disrupt carts.
Do it off-peak, or tighten -mtime carefully.
Step 8 — If you still can’t find it: check for hidden disk usage
If du and df don’t agree, a deleted file held open by a running process is the most common reason.
sudo lsof | grep '(deleted)' | head -50
Another common gotcha: a mount failed, and a job wrote into the mountpoint directory on the root filesystem instead.
Example: if /mnt/backups wasn’t mounted, your backup job may have written to /mnt/backups on /.
Confirm what’s actually mounted:
mount | column -t | head -50
Step 9 — Emergency space recovery plan (low risk, high impact)
If the server is pinned at 100% and apps are failing, start by freeing 2–5 GB.
Aim for space you can reclaim without touching customer data.
This sequence usually gets you breathing room:
- Vacuum systemd journal to 1G:
sudo journalctl --vacuum-size=1G - Truncate the single largest log in
/var/log(don’t delete):sudo truncate -s 0 /var/log/... - Clear package caches:
(On RHEL-like systems:sudo apt-get cleansudo dnf clean all) - Remove old kernels only if you know what you’re doing (this is usually safer to postpone).
Once you’re back under ~90% usage, the server typically “wakes up” again.
Temp files can be created, databases stop throwing “disk full,” and control panel actions stop timing out.
Step 10 — Prevention: put guardrails in place after the incident
Getting space back is the easy part.
The real win is avoiding the same page next month.
Set sane log retention
- Review
/etc/logrotate.d/and make sure critical services rotate daily or weekly. - Cap journald size in
/etc/systemd/journald.conf:[Journal] SystemMaxUse=1G SystemKeepFree=2G
Separate “web” from “system” storage on busy nodes
On larger VPS plans and dedicated servers, consider a separate volume for /home or /var/lib.
This limits the blast radius.
A runaway log shouldn’t take down uploads. A backup job shouldn’t starve the OS.
If you’re scaling from shared hosting to a server you control, HostMyCode VPS gives you the headroom and disk options to design this properly.
For high-traffic stores or multi-tenant reseller nodes, you may outgrow VPS entirely.
Then a dedicated server is the cleaner long-term fix.
Stop “backup-to-self” habits
Keep short local snapshots for quick rollbacks, but send real backups offsite.
If you need help planning a no-downtime move to bigger storage or a larger plan, HostMyCode also provides migration assistance.
Quick diagnostics checklist (copy/paste during an outage)
df -hT(what mount is full?)df -ih(blocks or inodes?)sudo du -xhd1 / | sort -h(largest top-level dirs)sudo find /var/log -type f -printf '%s %p\n' | sort -n | tail(largest logs)sudo journalctl --disk-usage(systemd journal size)sudo lsof +L1 | head(deleted but open files)docker system df(if Docker exists)
Summary: the reliable way to fix a full VPS disk
Start with df to identify the mount. Then confirm whether you’re out of blocks or inodes.
Use du to locate the biggest directories.
Clean up with intent: truncate runaway logs, vacuum journald, prune Docker carefully, and address mail queues or file storms.
After you stabilize the box, lock in retention policies and move backups off-server.
If you want the same playbook on infrastructure sized for growth, run it on a HostMyCode VPS, or choose managed VPS hosting to have an admin team handle prevention as well.
If you’re dealing with recurring “disk full” incidents, the plan is often undersized or the server is missing basic guardrails. Start with a HostMyCode VPS for predictable resources, or hand off day-to-day ops to managed VPS hosting so cleanup and prevention happen proactively.
FAQ
Should I delete files in /var/log to free space?
Prefer truncate -s 0 for active logs. Deleting an open log file may not free disk until the service restarts.
Why does df show 100% but du doesn’t add up?
Usually because a process still holds a deleted file open. Check with lsof +L1, then restart the service holding the file handle.
What’s the fastest safe way to free 1–2 GB immediately?
Vacuum journald (journalctl --vacuum-size=1G), truncate the single largest log file, and clear package caches (apt-get clean).
How do I prevent inode exhaustion on hosting servers?
Set cleanup for temp/session directories, avoid plugins that create huge file trees, and monitor file counts in cache paths. Inode issues come from “too many files,” not “big files.”