"No space left on device" never shows up at a convenient time. The database stops accepting writes, apt can't finish an upgrade, and Docker refuses to pull the image you need right now. The good news: on a small VPS the culprit is almost always one of five things, and you can find it in two minutes.
1. How bad is it?
df -h /
df -i /
The first line shows used space. The second shows inodes — if inodes hit 100% while space looks fine, you have millions of tiny files (session files, a mail queue, a cache directory). Different problem, same symptom.
2. Find what's big
Walk the tree from the top and sort by size:
du -xh / --max-depth=1 2>/dev/null | sort -h | tail -15
-x keeps it on one filesystem, so it won't wander into /proc. Then drill into whatever is largest. For interactive browsing, ncdu is much nicer:
apt install -y ncdu
ncdu -x /
Arrow keys to navigate, d to delete. Be careful with that last one.
3. The quick wins
These are safe on any Ubuntu or Debian server:
apt clean
apt autoremove --purge -y
journalctl --disk-usage
journalctl --vacuum-size=200M
apt autoremove also clears old kernels. The systemd journal is the one that surprises people — left alone it can grow to several gigabytes. To cap it for good, set SystemMaxUse=200M in /etc/systemd/journald.conf and run systemctl restart systemd-journald.
4. Docker leftovers
If you run Docker, check here first. Old images and build cache pile up with every deploy:
docker system df
docker image prune -a
docker builder prune
docker image prune -a deletes images that no running container uses. That's usually what you want, but the next deploy will pull them again.
The dangerous one is docker system prune -a --volumes. Volumes hold your data, and a volume attached to a stopped container counts as unused. People lose databases this way. Don't paste it from a forum answer.
Container logs are the other hidden hog. Cap them in /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": { "max-size": "10m", "max-file": "3" }
}
Restart Docker after that. The limit only applies to containers created afterwards, so recreate the noisy ones with docker compose up -d --force-recreate.
5. Logs and forgotten files
Find large files anywhere on the disk:
find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null
find /var/log -type f -size +100M -exec ls -lh {} + 2>/dev/null
The usual finds: a backup.tar.gz from six months ago in /root, a database dump someone meant to download, an app log that never rotates.
For a log that a service is still writing to, don't rm it — empty it:
truncate -s 0 /var/log/myapp/app.log
If you already deleted one and the space didn't come back, a process still holds it open:
lsof +L1
Restart the service listed there and the space returns.
When cleaning isn't enough
Sometimes the data is simply real — a growing database, user uploads, a model file. Then the honest fix is more disk. Upgrading the plan grows the disk in place and keeps everything: Nano has 15 GB, Micro 25 GB, Small 35 GB, Medium 45 GB. The server reboots once. Details are in the plans docs.
One more thing that eats space quietly: a swap file. If you followed our swap guide, that 1–2 GB is accounted for on purpose. And if Docker is the main consumer, the Docker install guide and the Compose stack guide show how to keep image sprawl in check.
The habit that prevents all of this: cap the journal and Docker logs on day one. Two config lines, and "disk full" mostly stops happening.
Comments
No comments yet. Be the first.