How to find what's using disk space on Linux and free it safely

Find what filled your server's disk with df, du and ncdu, then safely clean package caches, logs, old kernels and deleted files still held open.

Tested on Ubuntu 24.04 LTS, AlmaLinux 10

Before you start

  • A Linux server
  • Root or a user with sudo

To find what's using disk space on Linux, run df -h to see which file system is full, then sudo du -xh --max-depth=1 / | sort -h to see which top-level folder is big, and repeat du one level deeper until you reach the culprit. Most full disks on a server come down to five things: logs, package caches, old kernels, Docker images and backups someone forgot about. Each has a safe way to clean it, below.

The rule that keeps this safe: find out what a file is before you delete it, and never delete anything under /usr, /etc, /var/lib or /boot by hand. Use the tool that owns it instead. This tutorial was run on Ubuntu 24.04 and AlmaLinux 10.

See which disk is full

bash
df -h

Look at Use% for / (and any other mounted disk). Past about 90%, databases and package upgrades start failing in odd ways; at 100%, services can't write their logs or PID files and may refuse to start.

A disk can also run out of inodes (one per file) while it still has space, typically from millions of tiny cache or session files:

bash
df -i /

If IUse% is near 100%, look for the directory with the most files rather than the biggest one; the du commands below still point you there.

Find the biggest folders

Start at the top and walk down. -x stays on one file system, so it doesn't wander into /proc or other disks:

bash
sudo du -xh --max-depth=1 / 2>/dev/null | sort -h | tail -n 10

The last line is the total; the ones above it are the largest folders. Go one level into the biggest, for example /var:

bash
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -n 10

Repeat until you find it. On most servers it ends in /var/log, /var/lib/docker, /var/cache, /home or a backup directory.

Or browse it with ncdu

ncdu does the same walk interactively: arrow keys to move, Enter to open a folder, d to delete, q to quit.

bash
sudo apt install -y ncdu        # Ubuntu, Debian
sudo dnf install -y epel-release && sudo dnf install -y ncdu   # AlmaLinux, Rocky (from EPEL)
sudo ncdu -x /

Find the biggest files

bash
sudo find / -xdev -type f -size +100M -exec ls -lh {} + 2>/dev/null | awk '{print $5, $9}' | sort -h

This lists every file over 100 MB with its size. Typical finds: database dumps, .tar.gz backups, a forgotten ISO, a log file that was never rotated.

Clean the package cache

Package managers keep the files they downloaded. Removing them is always safe; they're downloaded again if needed.

bash
sudo apt clean                  # Ubuntu, Debian: empties /var/cache/apt/archives
sudo dnf clean all              # AlmaLinux, Rocky, Fedora: empties /var/cache/dnf

Then remove packages that were installed as dependencies and are no longer needed, which includes old kernels on Ubuntu and Debian:

bash
sudo apt autoremove --purge     # Ubuntu, Debian
sudo dnf autoremove             # AlmaLinux, Rocky

Read the list before you answer yes. On AlmaLinux and Rocky, old kernels are handled separately: dnf keeps the three newest (installonly_limit=3 in /etc/dnf/dnf.conf) and removes older ones on its own.

On Ubuntu, snap packages keep older revisions too. snap list --all shows them marked disabled; sudo snap set system refresh.retain=2 keeps fewer from now on.

Shrink the logs

The systemd journal is often the biggest single item in /var/log:

bash
journalctl --disk-usage
sudo journalctl --vacuum-size=200M

To keep it small for good, set SystemMaxUse= as shown in read logs with journalctl.

Text logs in /var/log are rotated and compressed by logrotate. Old compressed ones (*.gz, *.1) can go:

bash
sudo find /var/log -type f -name '*.gz' -mtime +30 -delete

If a single log keeps growing, don't delete it while the program is writing to it (see the next section). Empty it instead:

bash
sudo truncate -s 0 /var/log/myapp/app.log

Then fix the cause: an app logging at debug level, or a log with no logrotate rule. The files in /etc/logrotate.d/ are good examples to copy.

Deleted files that still take space

If you deleted a big file but df doesn't go down, a running program still has it open. The space is only freed when the program closes it. Find those files:

bash
sudo lsof +L1
text
COMMAND  PID USER   FD   TYPE DEVICE  SIZE/OFF NLINK   NODE NAME
myapp   3665 root    1w   REG  0,141 209715200     0 470591 /var/tmp/big.log (deleted)

Restarting that program (sudo systemctl restart myapp) frees the space. If you can't restart it now, empty the file through the program's open handle, using the PID and FD from the output (1w means descriptor 1):

bash
sudo truncate -s 0 /proc/3665/fd/1

Docker

Docker keeps old images, stopped containers and build cache in /var/lib/docker. Never delete files there by hand. See what it uses, then prune:

bash
docker system df
docker system prune

prune removes stopped containers, unused networks, dangling images and build cache. It doesn't touch volumes unless you add --volumes, and you shouldn't without checking what's in them: that's where container databases keep their data.

Troubleshooting

No space left on device but df -h shows free space. Check inodes with df -i. If they're full, find the directory with the most files: sudo du -x --inodes --max-depth=1 / | sort -n | tail.

df and du disagree by a lot. Deleted files that are still open (above), or files hidden under a mount point. sudo lsof +L1 covers the first.

apt or dnf fails because there's no room to download packages. Run sudo apt clean or sudo dnf clean all first; neither needs free space to work.

The disk fills again within days. Something writes continuously. sudo du -xh --max-depth=2 /var | sort -h | tail today and again tomorrow shows which folder grows.

Next steps

Doing it on VPSNine

On VPSNine, take a snapshot before a big clean-up so you can undo it. If you keep running out of room, the larger plans have more NVMe disk (40, 80 and 160 GB). When a server is so full it won't boot, rescue mode mounts its disk so you can clear space from outside. Works the same on Ubuntu 24.04 and AlmaLinux 10.

Be first when orders open

Join the waitlist and we'll send you one email when VPSNine launches. Pick a plan if you already know which one you want, and we'll size the first servers around it.

  • One email, on launch day
  • Monthly or yearly, no lock-in
  • 14-day money-back guarantee