I run a handful of Linux machines — a primary homelab server on a Dell OptiPlex, a low-power ARM box running Debian 11, and WSL2 on my daily driver. After about six months, every single one of them starts throwing "disk space low" warnings if I don't stay on top of cleanup. The worst offender so far was my ARM box's 16GB root partition — systemd journals alone had eaten 3GB before I noticed.
This guide covers every category of waste I've encountered and the exact commands I use to reclaim space. Industry research suggests that up to 30% of server disk space in production environments is wasted on unused logs, stale Docker images, and orphaned package caches. In my experience, that number is accurate — I regularly free 2-5GB from a typical self-hosted server after a thorough cleanup. For a 100GB root partition, that's 15-25GB of usable space, often enough to avoid costly resizing or migration.
I tested everything in this guide against Ubuntu 24.04 and Debian 11/12 — the two distros I run in production. Docker cleanup commands were tested with Docker 27.x on both platforms.
1. Identify Disk Usage
First, find out where the space went. The df and du commands are your primary tools — see their df(1) and du(1) man pages for all available options:
# Check overall usage
df -h
# Find the largest directories (starting from root)
sudo du -sh /* 2>/dev/null | sort -rh | head -10
# If /var or /home is particularly large, dig deeper
sudo du -sh /var/* 2>/dev/null | sort -rh | head -10
2. Log Cleanup (Usually the Biggest Culprit)
systemd journal Logs
Many servers accumulate 2-5GB of journal logs after a few months. According to the systemd journald documentation, the default journal size limit is just 10% of the filesystem size, which on a 100GB partition means up to 10GB of logs. Limit the size:
# Check current log usage
journalctl --disk-usage
# Immediately clean down to 200MB
sudo journalctl --vacuum-size=200M
# Keep only the last 7 days
sudo journalctl --vacuum-time=7d
# Permanent limit (edit config file)
sudo sed -i 's/^#SystemMaxUse=/SystemMaxUse=200M/' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald
Application Logs
Nginx, Docker, and other services also leave logs that need managing. Docker container logs are a particular pain — they write to individual JSON log files that can reach hundreds of megabytes each if left unchecked. I found this out when my Prometheus container's log file was 1.2GB before I even noticed:
# Nginx logs (usually in /var/log/nginx/)
sudo truncate -s 0 /var/log/nginx/*.log
# Docker container logs — check size first
sudo ls -lh /var/lib/docker/containers/*/*-json.log
# Then truncate
sudo sh -c 'truncate -s 0 /var/lib/docker/containers/*/*-json.log'
# Global Docker log limit (write to daemon.json — do this first, not after cleanup)
cat <<'EOF' | sudo tee /etc/docker/daemon.json
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
sudo systemctl restart docker
The daemon.json entry is the permanent fix. Before I added it, I was manually truncating Docker logs every few weeks. After setting max-size: 10m, each container caps at 30MB (3 files × 10 MB). Restarting Docker also restarts all running containers — plan for a brief service interruption.
3. Package Manager Cache
# apt cache
sudo apt autoremove -y # Remove unneeded dependencies
sudo apt clean # Clear .deb package cache
# Typically frees 200-500MB
# pip cache
rm -rf ~/.cache/pip/
# uv cache (if used)
uv cache clean
# npm cache
npm cache clean --force
4. Docker Disk Reclaim
Docker images, containers, and volumes often leave a lot of leftovers:
# One-command cleanup of all unused resources
docker system prune -af
# Also clean volumes (use with caution — deletes unused data volumes)
docker system prune -af --volumes
# Check specific usage
docker system df
5. Find Large Files
# Find files larger than 100MB
sudo find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null | sort -k5 -rh | head -20
# Find log files not modified for 7+ days and delete them
sudo find /var/log -type f -name "*.log" -mtime +7 -delete
6. One-Click Cleanup Script
Combine all of these into a script to run automatically every week:
#!/bin/bash
# /root/scripts/cleanup.sh
set -e
echo "=== (1/5) Cleaning apt ==="
sudo apt autoremove -y && sudo apt clean
echo "=== (2/5) Cleaning journal logs ==="
sudo journalctl --vacuum-size=200M
echo "=== (3/5) Cleaning pip cache ==="
rm -rf ~/.cache/pip/ 2>/dev/null | true
echo "=== (4/5) Cleaning Docker ==="
docker system prune -af 2>/dev/null | true
echo "=== (5/5) Current disk ==="
df -h / | tail -1
echo " Done ✅"
I run this script every Sunday at 3 AM on all my servers via a single cron entry. On my ARM box (16GB root partition), it typically frees 300-500MB per run — mostly from apt cache and journal logs. Schedule it: crontab -e and add 0 3 * * 0 bash /root/scripts/cleanup.sh &>/dev/null
If you're running Hermes Agent, you can also have the agent auto-run apt autoremove after system updates — I added that to my memory notes so it's handled without prompting.
FAQ
How often should I run disk cleanup on my Linux server?
For most servers, a weekly automated cleanup is sufficient. Set up a cron job that runs the cleanup script every Sunday at 3 AM. For high-traffic servers or those running Docker with frequent image builds, consider daily cleanup of Docker resources only.
Is it safe to run 'docker system prune -af' in production?
Generally yes, but be aware that it removes all stopped containers and unused images. If you have stopped containers you might need later, use docker system prune -f (without the -a flag), which skips unused images. The --volumes flag should be used with extra caution as it can delete data volumes permanently. For more on systemd journal management, refer to the journalctl(1) man page.
What is the best way to monitor disk usage proactively?
Set up disk usage alerts with tools like ncdu for interactive exploration, df for quick checks, and monitoring tools like Prometheus + Node Exporter or a simple cron script that sends a warning email when usage exceeds 85%. The du -sh /* command is the fastest way to find space hogs.
Why does /var/log keep growing even after I clean it?
Logs are generated continuously by running services. To prevent re-accumulation, configure logrotate (usually at /etc/logrotate.d/) with appropriate rotation policies, set Docker log limits in daemon.json, and limit the systemd journal size in journald.conf. Without these permanent limits, cleaning is only temporary.
Can deleting logs cause any problems?
Deleting active log files (files currently being written to) may cause the writing process to lose its file handle in some cases. Always use truncate -s 0 instead of rm for active log files. For rotated old logs, deletion is safe. System logs like journalctl are safe to clean via --vacuum-* commands.
Related Articles
- WSL2 Productivity Environment Setup — includes VHDX compression for disk space
- Automatic Backup Strategies — protect your data before cleanup
- Securing Your Self-Hosted Server — security audit after cleanup
- Docker Compose for Self-Hosting — manage containers efficiently