Debian 12 Disk Full: Troubleshooting & Resolving Inode Exhaustion (`df -i` 100%)
Diagnose and resolve inode exhaustion on Debian 12 Bookworm when `df -h` shows free space but services fail. Prevent critical system outages.
Diagnose and resolve inode exhaustion on Debian 12 Bookworm when `df -h` shows free space but services fail. Prevent critical system outages.
When your Debian 12 server starts behaving as if its disk is completely full – applications failing to write logs, new files failing to create, and web services returning "No space left on device" errors – it's natural to first check disk usage with df -h. However, if df -h reports ample free space, you're likely facing a less common but critical issue: inode exhaustion. This guide will walk you through diagnosing and resolving full inodes on your Debian 12 Bookworm system.
Symptom & Error Signature
The primary symptom is that your system, or specific applications, report "No space left on device" errors, or fail to create new files, even though standard disk space checks indicate free space.
You'll typically observe the following:
df -houtput (shows available space):df -h Filesystem Size Used Avail Use% Mounted on /dev/sda1 100G 20G 80G 20% / tmpfs 3.9G 0 3.9G 0% /dev/shm tmpfs 789M 1.1M 788M 1% /runNotice here,
/has 80G free and only 20% utilization.df -ioutput (shows 100% inode usage):df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda1 65536000 65536000 0 100% / tmpfs 1012546 744 1011802 1% /dev/shm tmpfs 1012546 792 1011754 1% /runCrucially,
/dev/sda1(mounted on/) shows 100%IUse%(inode usage). This is the smoking gun.Application Error Examples:
- Nginx/PHP-FPM: Error logs may show messages like:
2026/07/22 14:30:01 [crit] 1234#1234: *5432 open() "/var/cache/nginx/temp/1/00/0000000001" failed (28: No space left on device) PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (.../sess_xxxxxxxxxxxxx) in Unknown on line 0 - System Logs (
journalctl -xeor/var/log/syslog):systemd[1]: Failed to start Cleanup of Temporary Directories. kernel: EXT4-fs (sda1): VFS: Can't create inode for new file - Package Manager (
apt):E: mkstemp /tmp/apt.conf.XXXXXXXXXX failed (28: No space left on device) E: Could not create temporary file for /var/cache/apt/archives/partial/php_8.2-1~deb12u1_all.deb - mkstemp (28: No space left on device)
- Nginx/PHP-FPM: Error logs may show messages like:
Root Cause Analysis
An inode (index node) is a fundamental data structure in a Unix-like file system (such as ext4, XFS, etc.) that describes a file system object like a file or a directory. Each file or directory on your system requires exactly one inode. An inode stores metadata about the file, such as:
- Owner and group IDs
- Permissions
- Timestamps (creation, modification, access)
- File type (regular file, directory, symlink, block device, etc.)
- The actual disk block addresses where the file's data is stored.
When a file system is created, a fixed number of inodes are allocated. This number determines the maximum number of files and directories that can exist on that file system.
Inode exhaustion occurs when:
- Millions of small files are created. This is the most common scenario. Each of these tiny files, regardless of its size (even 0 bytes), consumes one inode. If you have millions of tiny files, you can exhaust all available inodes long before you run out of actual disk space.
- Common culprits include:
- Session files: Web applications (PHP, Node.js) often store session data as individual files.
- Cache files: Application caches (Nginx, Apache, PHP-FPM, web frameworks like Magento, WordPress) can generate countless temporary or cached files.
- Mail queues: Mail servers (Postfix, Exim) temporarily store individual emails as files in a queue directory.
- Temporary files: System-wide or application-specific
/tmpdirectories can accumulate many small, uncleaned files. - Docker artifacts: Old Docker layers, images, and container ephemeral data can create numerous small files.
- Log files: If not properly rotated, applications can create excessively granular or numerous log files.
- Package manager caches:
aptand other package managers can accumulate many small package lists and temporary files.
The system cannot create any new files, directories, or even symbolic links once all inodes are consumed, leading to the "No space left on device" error, even if df -h shows plenty of free blocks.
Step-by-Step Resolution
Follow these steps carefully to identify and clear the inode hogs on your Debian 12 system.
1. Verify Inode Exhaustion
Confirm the issue by checking both disk space and inode usage.
df -h # Check human-readable disk space
df -i # Check inode usage
If df -i shows 100% usage for your root filesystem (or a relevant mount point), proceed.
2. Identify Inode Hogs
The goal is to find which directories contain the largest number of files. We'll use find and wc -l (word count – lines) to count files.
The
findcommand can be resource-intensive on a struggling system. Useniceto lower its priority if performance is critical, andscreenortmuxin case your SSH session disconnects. Usesudoas needed to ensure you can access all directories.
First, identify the top-level directories that contain the most files:
echo "Counting files in top-level directories..."
for i in /*; do
if [ -d "$i" ]; then
printf "%-20s %sn" "$i:" "$(find "$i" -xdev -type f | wc -l)"
fi
done | sort -rn -k2 | head -10
This command iterates through root directories, counts all regular files (-type f) within them, prints the count, and then sorts to show the top 10. The -xdev flag is crucial to prevent find from crossing into other filesystems (e.g., separate /boot or mounted network shares), ensuring you're only counting files on the affected partition.
Once you've identified a suspicious directory (e.g., /var, /tmp, /home/user/cache), drill down into it. Let's assume /var was identified as having a high count.
echo "Counting files in subdirectories of /var..."
for i in /var/*; do
if [ -d "$i" ]; then
printf "%-30s %sn" "$i:" "$(find "$i" -xdev -type f | wc -l)"
fi
done | sort -rn -k2 | head -10
Repeat this process, drilling down into the directories that show the highest file counts. Common paths to investigate further are /var/lib/docker, /var/cache, /var/tmp, /var/www, /var/log, /var/spool.
Alternatively, you can use find to get the counts directly for subdirectories within a specific path:
# Example: Find top 10 directories with most files under /var/lib/docker
sudo find /var/lib/docker -xdev -type f -print0 | xargs -0 -n 1 dirname | sort | uniq -c | sort -rn | head -10
This command finds all files, extracts their directory names, counts occurrences of each directory, and lists the top 10 directories containing the most files.
3. Safely Clear Inode Hogs
Once you've pinpointed the offending directories, you need to safely remove the files. Be extremely cautious and double-check your commands. Deleting the wrong files can lead to data loss or system instability.
Always verify the contents of directories before mass deletion. Consider backing up critical data if unsure. For production systems, schedule downtime if possible.
a. Log Files (/var/log)
Excessive log files can quickly fill inodes.
- Rotate logs with
logrotate: Ensurelogrotateis properly configured for all applications.sudo logrotate -f /etc/logrotate.conf # Force rotation of all logs - Manually delete old log files:
# Delete log files older than 7 days in /var/log sudo find /var/log -type f -name "*.log" -mtime +7 -delete # Delete compressed log archives older than 30 days sudo find /var/log -type f -name "*.gz" -mtime +30 -delete # Delete specific application logs (e.g., Nginx access logs) sudo find /var/log/nginx -type f -name "access.log.*" -mtime +7 -delete
b. Temporary Files (/tmp, /var/tmp)
These directories are for temporary storage.
# Delete files in /tmp older than 1 day (use with extreme caution on active systems)
sudo find /tmp -type f -atime +1 -delete
# Delete files in /var/tmp older than 7 days
sudo find /var/tmp -type f -atime +7 -delete
Be very careful with
/tmpas active applications might be using temporary files.systemd-tmpfiles-clean.serviceusually handles this. For immediate relief, clearing older files is generally safe.
c. Web Application Cache/Session Files (/var/www, /var/cache)
Many web applications generate vast numbers of cache or session files.
Identify specific application directories:
/var/www/html/your-app/cache/var/www/html/your-app/sessions/var/cache/nginx(if Nginx caching is enabled)/var/cache/apache2(if Apache caching is enabled)
Example for Nginx cache:
sudo rm -rf /var/cache/nginx/* # Or for specific proxy caches sudo rm -rf /path/to/nginx/proxy_cache_dir/*Example for PHP session files:
sudo find /var/lib/php/sessions -type f -atime +1 -delete # Or, if your PHP applications use custom session paths, adjust accordingly. # Example: sudo find /var/www/html/my-app/sessions -type f -atime +1 -deleteExample for a specific application's cache (e.g., WordPress/Magento/Laravel):
# Example: For a WordPress installation sudo find /var/www/html/wordpress/wp-content/cache -type f -atime +1 -delete # Example: For a Laravel installation sudo rm -rf /var/www/html/laravel-app/bootstrap/cache/* sudo rm -rf /var/www/html/laravel-app/storage/framework/cache/data/*Always consult your application's documentation for safe cache clearing methods.
d. Docker Data (/var/lib/docker)
Docker can accumulate many unused images, containers, and volumes, creating numerous small files.
# Clean up unused Docker objects: stopped containers, unused networks, dangling images
sudo docker system prune
# Clean up all unused Docker objects including unused images, volumes and build cache
sudo docker system prune -a
# Clean up unused volumes (use with caution, can delete important data)
sudo docker volume prune
docker system prune -acan delete data that might be needed later (e.g., build cache). Use it judiciously, especiallydocker volume prune. Ensure you don't delete volumes containing persistent data.
e. APT Cache (/var/cache/apt)
The package manager's cache can also accumulate files.
sudo apt clean # Removes downloaded package files (.deb)
sudo rm -rf /var/lib/apt/lists/* # Clears package lists cache, will be rebuilt on next apt update
f. Mail Queues (/var/spool/postfix, /var/spool/exim4)
If your server sends a lot of email, especially failed deliveries, mail queues can grow large.
- Postfix:
sudo postsuper -d ALL # Deletes all messages from the Postfix queueThis irrevocably deletes all pending emails in the queue. Only use if you understand the implications.
- Exim:
sudo exim -qff # Force delivery attempt for all messages # Or to delete all messages: sudo find /var/spool/exim4/input -type f -deleteThis irrevocably deletes all pending emails in the queue.
After performing cleanup, re-check your inode usage:
df -i
You should see a significant drop in IUse%. If not, repeat step 2 and 3 to find more inode hogs.
4. Monitor Inode Usage
Once resolved, set up proactive monitoring to prevent future recurrences.
- Manual Check: Use
watch -n 60 "df -i"to monitor inode usage every 60 seconds. - Monitoring Tools: Integrate
df -ioutput into your existing monitoring stack (e.g., Prometheus Node Exporter, Nagios, Zabbix). Look for metrics related tonode_filesystem_inodes_freeandnode_filesystem_inodes_total.
5. Prevent Future Inode Exhaustion
Proactive measures are key to maintaining a healthy system.
- Configure
logrotateproperly: Review/etc/logrotate.d/for all applications, ensuring logs are rotated, compressed, and old ones are removed. Create customlogrotateconfigurations for applications writing logs outside standard locations.# Example /etc/logrotate.d/nginx /var/log/nginx/*.log { daily missingok rotate 7 compress delaycompress notifempty create 0640 www-data adm sharedscripts prerotate if [ -d /run/systemd/system ]; then systemctl reload nginx.service > /dev/null 2>&1 || true else /etc/init.d/nginx reload > /dev/null 2>&1 || true fi endscript } - Application-Specific Cleanup:
- Web Server Caches: Configure Nginx/Apache cache management settings (e.g.,
proxy_cache_path ... inactive=1d max_size=10g manager_frequency=1h). - Application Caches: Implement application-level cron jobs or built-in mechanisms to clear old session files, temporary files, and cache entries.
- Web Server Caches: Configure Nginx/Apache cache management settings (e.g.,
- Regular Docker Pruning: Schedule
docker system prune(without-afor caution) as a weekly or monthly cron job.# Example cron job to run weekly 0 0 * * 0 /usr/bin/docker system prune -f > /dev/null 2>&1 - Monitor Mail Queues: Regularly check mail server queues for excessive messages.
- Filesystem Choice: For new deployments that anticipate storing a huge number of small files (e.g., object storage backends, heavily cached applications), consider using filesystems like XFS, which can dynamically allocate inodes or generally handle larger inode counts more efficiently than ext4 in some configurations.
Changing a filesystem type (e.g., from ext4 to XFS) requires reformatting the partition, which will erase all data. This is a destructive operation and should only be considered for new systems or when you can completely back up, reformat, and restore data.
By understanding the nature of inodes and implementing robust cleanup and monitoring strategies, you can prevent future inode exhaustion issues and maintain the stability and performance of your Debian 12 servers.