Free Disk Space on Ubuntu

Khimananda Oli 9 min read Virtualization
Free Disk Space on Ubuntu

By Khimananda Oli | Last reviewed: August 2026

Running out of storage is one of the most common causes of unexpected downtime on Linux servers. When you need to free disk space on Ubuntu, the priority is identifying safe targets like package caches, rotated logs, and orphaned containers before touching application data. This guide provides the exact diagnostic and cleanup workflow I use in production environments to recover gigabytes quickly without risking service stability or data integrity.

How do you accurately diagnose disk usage before cleaning?

Before deleting anything, you must distinguish between actual disk consumption and inode exhaustion, as they require completely different remediation strategies. A common mistake engineers make when trying to diagnose high resource usage is assuming that a "No space left on device" error always means the disk is physically full. In reality, your filesystem might have plenty of bytes available but zero free inodes, which happens frequently on mail servers or systems generating millions of small temporary files.

Disk Space Diagnostic Workflowdf -h && df -iInodes Exhausted (100%)Find small file clusters:find / -xdev -printf '%h\n' | \sort | uniq -c | sort -rnDisk Full (Bytes)Find large files on root:du -ahx / | sort -rh | head -20(Excludes mounted volumes)Deleted Files Still Held Open?lsof +L1 | grep deleted
Decision tree for diagnosing whether disk pressure comes from byte exhaustion, inode limits, or held-open deleted files

Start with df -h to see human-readable filesystem usage and df -i to check inode utilization. If inodes are at 100% but disk usage shows only 40%, you have a small-file problem. Use find /var -xdev -type f | wc -l to count files in suspect directories. For byte-level analysis, always use the -x flag with du to avoid traversing into mounted volumes like /proc, /sys, or separate data partitions. The command sudo du -ahx / | sort -rh | head -20 gives you the twenty largest items strictly on the root filesystem, which is usually where the emergency lies.

A third scenario catches many engineers off guard: files that have been deleted but are still held open by running processes. The space won't be released until the process closes the file descriptor or restarts. Check this with sudo lsof +L1 | grep deleted. If you see multi-gigabyte log files in this output, restarting the relevant service (often rsyslog, nginx, or a Java application) will instantly reclaim that space without any manual deletion.

How do you safely clean APT caches and old kernels on Ubuntu?

The Advanced Package Tool (APT) accumulates significant debris over time. On long-lived servers, especially those receiving regular security patches, the package cache and orphaned dependencies can consume several gigabytes. This is typically the safest place to begin when you need to free disk space on Ubuntu because these operations are fully reversible through reinstallation.

  1. Purge removed packages: Run sudo apt autoremove --purge. The --purge flag is critical; without it, configuration files remain on disk even after the package binaries are removed. This single command often recovers 500MB to 2GB on neglected systems.
  2. Clean the package cache: Execute sudo apt clean to remove all cached .deb files from /var/cache/apt/archives/. Unlike apt autoclean (which only removes obsolete versions), apt clean empties the entire cache. Since packages can be re-downloaded on demand, this is safe for production.
  3. Remove old kernels: Ubuntu retains previous kernel versions for rollback safety. List installed kernels with dpkg --list | grep linux-image. Never remove the currently running kernel (uname -r). Remove older versions with sudo apt purge linux-image-X.X.X-XX-generic. On systems that haven't been cleaned in years, this alone can free 3–5GB.
  4. Clean residual configs: Find packages in "rc" state (removed but config remains) using dpkg -l | grep ^rc. Purge them all at once with dpkg -l | grep ^rc | awk '{print $2}' | sudo xargs dpkg --purge.

Always verify your bootloader configuration after kernel removal by running sudo update-grub. While APT handles this automatically in most cases, confirming ensures you don't accidentally boot into a missing kernel during the next maintenance window.

What is the correct way to manage systemd journal and log rotation?

Systemd journals are a frequent silent consumer of disk space. By default, journald may store up to 10% of your filesystem size in binary logs under /var/log/journal/. On a 100GB root partition, that's potentially 10GB of logs you may never query. Proper log rotation and disk management prevents this from becoming a recurring crisis.

<!-- Check current journal usage -->
journalctl --disk-usage

<!-- Vacuum to a specific size limit -->
sudo journalctl --vacuum-size=100M

<!-- Or retain only recent time period -->
sudo journalctl --vacuum-time=7d

<!-- Make persistent configuration change -->
sudo nano /etc/systemd/journald.conf
# Set: SystemMaxUse=100M
# Set: MaxRetentionSec=1week
sudo systemctl restart systemd-journald

Beyond journald, check traditional text logs in /var/log/. Applications writing verbose debug output can generate massive files between logrotate cycles. Use sudo find /var/log -type f -size +100M to locate oversized logs. Before truncating active log files, never use rm; instead use truncate -s 0 /var/log/filename.log or redirect with : > /var/log/filename.log. Deleting an open file doesn't free space until the writing process releases its handle, whereas truncation works immediately while preserving the inode the process expects.

Review your logrotate configuration in /etc/logrotate.d/. Ensure compression is enabled (compress directive) and retention periods match your compliance requirements. For SOC 2 or ISO 27001 environments, you may need longer retention; configure offsite shipping to S3 or a centralized logging stack so local retention stays lean. If you're running workloads that benefit from AI-powered log analysis, ship logs externally rather than hoarding them locally.

Safe Cleanup Execution Order1. Diagnosedf -h, du -ahx2. APT Cleanautoremove --purge3. Journalsvacuum-size=100M4. Dockersystem prune -a5. Old Kernelsapt purge linux-image6. App Cachesnpm/pip/composer7. Manual ReviewLarge files audit8. Verifydf -h + services OK⚠ Safety Rules• Never delete files in /proc, /sys, /dev, or /run• Truncate active logs; never rm open files • Test services after each step
Ordered cleanup pipeline prioritizing safe automated operations before manual intervention, with safety guardrails

How should you handle Docker and container storage cleanup?

Docker is frequently the single largest consumer of disk space on modern Ubuntu servers. Unused images, stopped containers, dangling build cache, and orphaned volumes accumulate silently. On CI runners and development servers, Docker can easily consume 50–100GB within weeks if not managed proactively.

CommandWhat It RemovesRisk LevelTypical Recovery
docker container pruneStopped containers onlyLow100MB–2GB
docker image prune -aAll unused images (not just dangling)Medium5–30GB
docker volume pruneUnnamed volumes not attached to containersHigh1–50GB
docker builder pruneBuildKit cache layersLow2–20GB
docker system prune -a --volumesAll of the above combinedHigh10–80GB

The aggressive docker system prune -a --volumes command is powerful but dangerous. It removes anonymous volumes that may contain database state from improperly configured compose stacks. Always list volumes first with docker volume ls and inspect suspicious ones with docker volume inspect <name> before pruning. For production systems, prefer targeted cleanup: prune stopped containers and dangling images first, then address volumes individually.

For ongoing management, configure Docker's log driver to prevent container logs from growing unbounded. Add "log-driver": "json-file" and "log-opts": {"max-size": "10m", "max-file": "3"} to /etc/docker/daemon.json. Without this, a single verbose container can fill your disk overnight. Teams adopting Docker containerization should bake these defaults into their base server provisioning from day one.

When should you automate disk space monitoring versus manual cleanup?

Reactive cleanup works for emergencies, but sustainable operations require proactive monitoring. If you're manually freeing disk space on Ubuntu more than once per quarter, you need automation. The threshold depends on your growth rate and operational tolerance; I recommend alerting at 75% usage and taking automated action at 85%.

  • Set up monitoring alerts: Use node_exporter with Prometheus, or CloudWatch Agent on AWS, to track node_filesystem_avail_bytes. Configure alerts at 75% (warning) and 85% (critical). This gives you hours or days to respond instead of minutes.
  • Automate safe cleanup via cron: Schedule apt autoremove --purge and journalctl --vacuum-size=100M weekly. These are idempotent and risk-free. Do not automate docker system prune or volume cleanup without explicit approval workflows.
  • Implement log shipping: Rather than retaining months of logs locally, ship to a centralized platform. This aligns with ELK stack best practices and keeps local disk usage predictable regardless of traffic spikes.
  • Right-size your volumes: If you're consistently above 70% usage even after cleanup, your provisioning is wrong. Expand the volume or migrate to larger storage. Disk is cheap; outage recovery is expensive.
Reactive vs Proactive Disk ManagementTime →Disk Usage %85% AlertEmergencyOutagePanicProactive ApproachStable ~65-70% usageAutomated vacuums + alertsReactive ApproachSawtooth: 95% → panic clean → 40%Repeated fire drills + downtime risk
Reactive cleanup creates volatile sawtooth disk usage patterns with outage risk, while proactive monitoring maintains stable headroom

For teams managing multiple servers, consider infrastructure-as-code approaches to enforce consistent disk hygiene. Tools like Ansible can deploy standardized logrotate configs, journald settings, and cleanup cron jobs across your fleet. This eliminates configuration drift that inevitably leads to one server silently filling up while others remain healthy. If you're building new infrastructure, integrating these patterns during initial server setup prevents technical debt from accumulating in the first place.

Sustainable Disk Hygiene for Production Ubuntu Servers

Freeing disk space on Ubuntu is straightforward when you follow a methodical diagnostic-first approach. Start with safe, reversible operations like APT cache cleaning and journal vacuuming before progressing to higher-risk targets like Docker volumes and manual file deletion. Automate the safe operations, monitor proactively, and treat repeated emergencies as a signal to fix underlying architecture rather than just cleaning up symptoms. If your team needs help establishing sustainable disk management practices or auditing existing infrastructure for compliance readiness, reach out to discuss your environment.

Frequently Asked Questions

Run df -h in terminal to view human-readable filesystem usage. This command displays total, used, and available space for all mounted partitions including root and home directories.

Yes, df shows filesystem-level free space while du reports actual file and directory sizes. Use both together for accurate diagnosis of missing storage blocks.

Reserved blocks for root user typically consume five percent of ext4 filesystems. Adjust this with tune2fs -m 1 /dev/sdX to reclaim space on non-root data volumes safely.

Execute sudo ncdu / to interactively browse directory sizes sorted by consumption. This tool identifies specific folders and files hogging storage without complex find command syntax.

Yes, run sudo journalctl --vacuum-size=100M to limit systemd journals to 100 megabytes. Never delete log files manually as this breaks rotation and auditing compliance requirements.

Run sudo apt autoremove --purge followed by sudo apt clean to remove obsolete packages and cached deb files. This safely reclaims hundreds of megabytes after system upgrades.

Millions of small files consume inodes before filling storage blocks. Check usage with df -i and locate dense directories using find / -xdev -printf '%h\n' | sort | uniq -c | sort -rn.

Extend the logical volume with lvextend -r -L +10G /dev/vg/lv then resize the filesystem online. The -r flag handles ext4 and xfs resizing automatically without unmounting production data.

Btrfs offers transparent compression and snapshots reducing effective storage needs but adds CPU overhead. Ext4 remains faster for pure throughput workloads where raw free space matters more than features.

Configure Prometheus node_exporter with alertmanager rules triggering at eighty-five percent capacity. This provides proactive warnings before outages occur in production Kubernetes or bare-metal environments during 2026 deployments.

Yes, open file handles prevent space reclamation until processes release them. Identify culprits with sudo lsof +L1 and restart services or truncate files to immediately recover ghost storage blocks.

Stop docker service, rsync /var/lib/docker to new mount, update daemon.json data-root parameter, then restart. Verify containers run correctly before removing original directory to avoid data loss.

Maintain at least ten percent free space on root partition for package operations and temporary files. Below this threshold, apt transactions fail and system updates become impossible without manual cleanup.

Set zfs set compression=lz4 pool/dataset on existing datasets without remounting. LZ4 provides near-realtime compression with minimal CPU penalty, often doubling effective capacity for text and log workloads.

Yes, snaps retain multiple versions consuming gigabytes. Remove old revisions with sudo snap list --all | awk '/disabled/{print $1, $3}' | xargs -n2 sudo snap remove --revision to reclaim substantial storage.