Running out of disk space
A VPS disk doesn't warn you before it fills up — usually you find out from the fallout: the site starts returning 500 errors, apt/dnf refuses to install packages, MySQL writes Disk full to its log, and No space left on device shows up in command output and system logs. This article covers how to quickly find what's actually eating the space, free it up safely, and what to do once there's nothing left to free.
What you'll need
- SSH access as
rootor a user withsudo— the commands below need administrator privileges. - An mHost VPS running Ubuntu 22.04/24.04, Debian 11/12, or AlmaLinux/Rocky Linux 8/9 — Steps 1–7 (the command line) are written for these systems; Step 8 (expanding the disk in VMmanager 6) works the same way for Windows servers too.
- Access to the VMmanager 6 panel — you'll need this if there still isn't enough space after cleaning up (Step 8).
Step 1. Find which partition ran out of space
Start with the big picture: df (disk free) shows how much space is used and available on each mounted partition.
df -hThe -h (--human-readable) flag prints sizes in convenient units (K, M, G) instead of bytes. Example output:
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 38G 1.2G 97% /
tmpfs 2.0G 0 2.0G 0% /dev/shm
/dev/vda15 105M 6.1M 99M 6% /boot/efiLook at the Use% column. On most VPS everything lives on a single / partition, but if /home, /var, or a database has its own separate partition, that's the one that might actually be full — note the exact Mounted on value and run every following step against that partition.
A disk can also "run out" without Use% hitting 100% — if you've run out of inodes (the limit on the number of files, not their total size):
df -iIf IUse% there is close to 100% while the actual space looks fine, the problem isn't file size but file count (a typical example is millions of tiny session or cache files). Steps 2–7 below still help in this case too — you find the offending directory the same way and clean it up.
Step 2. Find out what's actually taking up the space
Next, track down the specific offenders with du (disk usage), drilling down the directory tree level by level.
du -sh /* 2>/dev/null | sort -rh | head -n 20-s(--summarize) — don't list the contents of each directory, just show the grand total for it.-h— sizes in human-readable form.2>/dev/null— hide "permission denied" errors for directories you can't read.sort -rh— sort by descending size.
Take the largest directory from the output and repeat the command inside it:
du -sh /var/* 2>/dev/null | sort -rh | head -n 20Keep drilling down the same way until you see specific files or directories you can actually clean up. Common culprits on a VPS: /var/cache (Step 3), /var/log (Step 5), /var/lib/docker (Step 6), and directories holding backups or database dumps if you keep them on the same disk — see "Scheduled backups with cron" and "Database backups", which also cover moving copies off the server.
du -x --max-depth=1 / 2>/dev/null | sort -rh | head -n 20-x stops du from crossing into other mounted filesystems at all — unlike the asterisk-based command above, this one shows only what actually lives on the / partition, and /proc, /sys, and any other partition (a separate /home, say) come back empty.
Step 3. Clear the package manager's cache
apt and dnf both keep already-downloaded .deb/.rpm packages on disk — after a few rounds of updates this can add up to a couple of gigabytes.
Ubuntu / Debian
Check how much the cache is using first:
du -sh /var/cache/apt/archives/Clear it:
apt cleanapt clean removes everything from /var/cache/apt/archives/ — apt will simply re-download already-installed packages if it ever needs them again. Also remove dependencies left behind by removed packages that nothing needs anymore:
apt autoremove --purge--purge also deletes the leftover config files (in /etc) of packages that are no longer needed, not just the packages themselves.
AlmaLinux / Rocky Linux
Check the cache:
du -sh /var/cache/dnf/Clear it:
dnf clean allUnlike dnf clean packages (downloaded packages only), dnf clean all also clears the cached repository metadata — dnf will just re-download it on the next command. Remove unused dependencies:
dnf autoremoveStep 4. Clean up the systemd journal (journald)
journald — systemd's logging service — stores the journal in binary form, and on some servers it grows over time, especially if some service is logging way more than it should.
Check how much space the journal is using right now:
journalctl --disk-usageExample output:
Archived and active journals take up 3.2G in the file system.Trim the journal down to a target size:
journalctl --vacuum-size=500MThis removes the oldest archived (already rotated) journal files until the total footprint is under 500M — the active file currently being written to isn't touched, so it's safe. Instead of a size, you can cap the journal by age:
journalctl --vacuum-time=30d(keeps only entries newer than 30 days)
cat >> /etc/systemd/journald.conf <<'EOF'
[Journal]
SystemMaxUse=500M
EOFsystemctl restart systemd-journaldYou can turn on persistent journal storage (and the limit from the example above) like this — the command creates the directory and asks systemd-tmpfiles to initialize it; no restart needed, journald picks up the directory on its own:
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journalStep 5. Find and clean up large logs
Check what's actually heavy inside /var/log:
du -sh /var/log/* 2>/dev/null | sort -rh | head -n 20logrotate is already installed and configured on every supported distribution — it runs automatically once a day (via the systemd timer logrotate.timer on newer Ubuntu/Debian, or the classic /etc/cron.daily/logrotate job elsewhere) and compresses and removes old log copies according to the rules in /etc/logrotate.d/. Check which mechanism your server actually uses:
systemctl list-timers | grep logrotateYou don't have to wait — force logrotate to run right now:
logrotate -f /etc/logrotate.conf-f (--force) rotates every configured log immediately, even if it hasn't hit its size or age threshold yet. If one particular log keeps growing and the default rules aren't enough, add a dedicated config for it:
cat > /etc/logrotate.d/myapp <<'EOF'
/var/log/myapp/*.log {
daily
rotate 7
compress
missingok
notifempty
}
EOFThis rule rotates *.log under /var/log/myapp/ daily, keeps the 7 most recent copies, compresses them (compress), and doesn't complain if the file or new entries are missing (missingok, notifempty).
Find these "ghost" files — open, but already deleted:
lsof +L1 2>/dev/null | head -n 20If lsof isn't installed:
# Ubuntu/Debian
apt install lsof
# AlmaLinux/Rocky Linux
dnf install lsof+L1 lists open files whose link count is below 1 — exactly the "deleted but still open" case. The COMMAND and PID columns show which process is holding the file, and SIZE shows how much space it's still using. You can free the space without restarting the service by truncating the file through the process's own file descriptor:
truncate -s 0 /proc/<PID>/fd/<FD>Substitute <PID> and <FD> with the values from the lsof output.
Step 6. If you're running Docker — clean up unused data
Docker keeps images, stopped containers, unused networks, and build cache under /var/lib/docker (see "Docker and Docker Compose" for details) — on a server running containers, this is often the single biggest consumer of disk space.
See the breakdown by type first:
docker system dfThis prints TYPE (Images, Containers, Local Volumes, Build Cache), TOTAL, ACTIVE, and SIZE/RECLAIMABLE — how much space you could free without losing anything.
Safe cleanup:
docker system pruneThis removes stopped containers, networks with no containers attached, dangling (untagged) images, and unused build cache. It doesn't touch volumes or images that still carry a tag, even if nothing's used them in a while.
To also remove every unused image (not just untagged ones) and every unused volume:
docker system prune -a --volumesStep 7. Find large files individually
Sometimes the space isn't spread across a whole directory but sitting in one or two individual files — a forgotten database dump, a core dump from a crashed process, an ISO uploaded once for a one-off task and never removed.
find / -xdev -type f -size +100M -exec ls -lh {} \; 2>/dev/null-xdev— same purpose as-xforduin Step 2: stay on the current filesystem, skipping other mounted partitions (and/procalong with them).-type f— regular files only, not directories or devices.-size +100M— only files larger than 100 MB (change the threshold to, say,+1Gif needed).-exec ls -lh {} \;— print the size and path of each match in human-readable form.
If there are a lot of matches, sort them by size:
find / -xdev -type f -size +100M -printf '%10s %p\n' 2>/dev/null | sort -rn | head -n 20Step 8. If there's still not enough space — expand the disk
If there's still little free space left after all the previous steps, the only option left is to grow the disk itself. Depending on your plan, that means either upgrading the plan as a whole or expanding just the disk without changing the rest of the server's specs — check the exact option for your plan in the my.mhost.ee account panel or with mHost support.
The expansion itself happens in the VMmanager 6 panel (for how to log in, see "How to log in to VMmanager 6"):
- Open the "Virtual machines" section and select your server.
- Click the "Parameters" button.
- Go to the "Fine-tuning" section → the "VM disk configuration" tab.
- In the Storage field, enter the new, larger disk size in gigabytes — you can only increase the disk from the panel, never shrink it.
📷 screenshot: the "VM disk configuration" tab under VMmanager 6's fine-tuning settings
From here there are two options:
- The "Increase disk size without VM reboot" checkbox is on — the disk grows on the fly, with no server downtime. This only works for ext4, xfs, and ntfs filesystems, and only if the disk is attached through a VirtIO controller.
- The checkbox is off — the resize happens with a server reboot, and you additionally need to specify which partition (Partition) to expand into — VMmanager grows it automatically during the reboot. This method doesn't depend on the disk controller type — use it if the checkbox above is unavailable or didn't work.
After a no-reboot disk expansion, the operating system doesn't see the new space yet — it exists on the disk itself, but not in the partition or the filesystem. Identify the device and partition name (usually already visible in the df -h output from Step 1 — in that example, the root partition is on /dev/vda1, i.e. partition 1 of disk /dev/vda; if unsure, check with lsblk), then expand the partition and the filesystem from inside the OS:
lsblkgrowpart /dev/vda 1For ext4:
resize2fs /dev/vda1For xfs, the command takes the mount point, not the device:
xfs_growfs /If the growpart command isn't available:
# Ubuntu/Debian
apt install cloud-guest-utils
# AlmaLinux/Rocky Linux
dnf install cloud-utils-growpartIf you expanded the disk with a server reboot (checkbox off), check df -h after it comes back up: if the new size is already there, there's nothing more to do; if not, expand the filesystem with the same resize2fs/xfs_growfs commands as above.
Windows: open Disk Management, right-click the partition that now has unallocated space next to it, and choose "Extend Volume".
Prevention: set up disk monitoring
Cleaning up a disk by hand after the site has already gone down is a bad strategy. The right approach is to find out about low disk space in advance, from an alert, rather than after the fact from an outage.
Set up Zabbix and connect your server to it — the "Monitoring with Zabbix" article covers installing the server and agent on an mHost VPS. The standard "Linux by Zabbix agent" template auto-discovers every mounted filesystem and already ships with triggers for low disk space — a warning by default at 80% full and a critical alert at 90% (the {$VFS.FS.PUSED.MAX.WARN} and {$VFS.FS.PUSED.MAX.CRIT} macros). You can adjust these thresholds per partition — for example, raising it for a logs partition where 90% full is normal operating conditions.
What's next
If the disk fills up quickly and repeatedly rather than as a one-off, the likely cause is the application itself: logs that keep growing, a cache nobody clears, or backups piling up on the same disk instead of being moved off the server — see "Scheduled backups with cron", "Backups with rsync", and "Incremental backups with restic". If the site didn't come back on its own once space ran out, "My website won't load" and "A service won't start" can help you dig further. And if, on the other hand, there's plenty of disk and resources but the server still crawls, that's the subject of "High server load".