Common Issues

/boot Partition Full: Removing Old Kernels

/boot partition full and apt can't update? Safely remove old Linux kernels to free space.

On Ubuntu and Debian, each kernel update leaves the old one in the /boot partition. Over time they accumulate until the partition (typically 500 MB) fills up and apt stops working with errors like:

E: Failed to fetch ... No space left on device
dpkg: error processing package linux-image-...

Diagnosis

# Check space on /boot
df -h /boot

# List installed kernels
dpkg --list | grep linux-image

# Currently running kernel (DO NOT remove this!)
uname -r

Quick solution (Ubuntu)

# Automatically remove unused kernels (safe method)
apt autoremove --purge

apt autoremove removes old kernels no longer needed, keeping current kernel and the previous one. It's the safest method.

Don't remove running kernel

Never remove the kernel returned by uname -r. If something goes wrong, you won't be able to boot the server.


If apt can't run due to lack of space

When /boot is completely full, even apt won't work. Solution:

# Find installed kernels
dpkg --list | grep linux-image | awk '{print $2}'

# Example output:
# linux-image-5.15.0-91-generic
# linux-image-5.15.0-94-generic
# linux-image-5.15.0-97-generic   ← this is the current one (uname -r)

# Remove manually the old ones (NOT the current one)
dpkg --purge linux-image-5.15.0-91-generic
dpkg --purge linux-image-5.15.0-94-generic

# Now apt should work again
apt autoremove --purge
apt clean

Remove kernels with script

# List all kernels except the active one
CURRENT=$(uname -r)
dpkg --list | grep linux-image | grep -v "$CURRENT" | grep "^ii" | awk '{print $2}'

# Remove them all at once
dpkg --list | grep linux-image | grep -v "$(uname -r)" | grep "^ii" | awk '{print $2}' | xargs apt-get -y purge

Remove old headers and modules too

# Remove headers corresponding to removed kernels
apt autoremove --purge linux-headers-\*

# Or more precisely
dpkg --list | grep linux-headers | grep -v "$(uname -r | cut -d- -f1,2)" | grep "^ii" | awk '{print $2}' | xargs apt-get -y purge

Clean apt cache

After removing kernels, also free up cache:

apt clean          # empty /var/cache/apt/archives
apt autoclean      # remove only packages no longer downloadable

df -h /boot        # verify freed space

Prevention for the future

Regularly check /boot

# Add alert to cron if /boot exceeds 70%
echo '0 8 * * * root USAGE=$(df /boot | awk "NR==2{print \$5}" | tr -d "%"); if [ $USAGE -gt 70 ]; then echo "/boot at ${USAGE}% on $(hostname)" | mail -s "ALERT: /boot almost full" root; fi' > /etc/cron.d/check-boot

Configure GRUB to keep fewer kernels

nano /etc/default/grub
# Keep only the last 2 kernels (default is unlimited)
GRUB_DEFAULT=0

Then:

echo 'Dpkg::AutoRemove::SuggestsImportant "false";' > /etc/apt/apt.conf.d/99nosuggests

Ubuntu: use unattended-upgrades with purge

# In /etc/apt/apt.conf.d/50unattended-upgrades
# Add:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-New-Unused-Dependencies "true";

On this page