How to Remove Old Kernels and Free /boot on Ubuntu
When /boot full, apt fit show errors and stop configuring packages. See which linux-image packages you fit remove safely, keep your running kernel, and fix installs.
Why apt no longer dey work when /boot full of old kernels
For Ubuntu, every kernel update dey write new set of files inside /boot and leave the old ones there. Because of this, small /boot partition fit full, and apt no fit complete installation again. The repair get two steps. Find out which packages for the box be kernels and which one you booted with. Then remove the others with apt autoremove --purge.
The order dey important. The kernel wey dey run na the package wey you must not remove. The box fit don already enter state where apt no fit run at all. Diagnose first.
Wetin the failure really looks like
One kernel version dey install two big files for /boot: the compressed kernel (vmlinuz-<version>) and the initramfs (initial RAM filesystem, initrd.img-<version>, the small archive wey kernel dey unpack before e mount the real root). Your machine dey build the initramfs when e dey install, na why the install need free space and no be only download bandwidth. If space finish, the build fail and e carry the package fail too.
update-initramfs: Generating /boot/initrd.img-6.8.0-64-generic
gzip: stdout: No space left on device
E: mkinitramfs failure gzip 1
update-initramfs: failed for /boot/initrd.img-6.8.0-64-generic with 1.
dpkg: error processing package linux-image-6.8.0-64-generic (--configure):
installed linux-image-6.8.0-64-generic package post-installation script subprocess returned error exit status 1The version string go be your own. The compressor name come from COMPRESS= inside /etc/initramfs-tools/initramfs.conf, so newer image fit name zstd while older one name gzip. The two lines wey identify this problem na No space left on device and the dpkg: error processing package line under am.
After that, the package remain half-configured. Every later apt run go try configure am again, fail the same way, and end with E: Sub-process /usr/bin/dpkg returned an error code (1). This na the part wey matter beyond disk space: unattended-upgrades dey run according to its timer, hit the same error, and stop. The server go look healthy but e go quietly stop applying security patches. E also mean say any unrelated install wey you try go fail with that same line, and the blame go land on wetin you dey add at that time. Na why Tailscale install wey fail for Ubuntu worth reading first as an apt error. If apt update fail before you reach this point, na separate problem, often duplicate entry after the deb822 sources migration.
Check whether /boot na separate partition
Before you delete anything, find out wetin you really dey free.
findmnt /boot
findmnt -T /boot
df -h /boot /The first command go print line only if /boot dey as e own mount point. The second one go always print, and e go name the filesystem wey really dey hold /boot. If dem name the same filesystem as /, e mean say /boot na just directory for the root filesystem, and e no fit full by itself: your root filesystem don full, and old kernels na only one of many contributors. For this case, sudo apt clean, wey dey empty the downloaded .deb files under /var/cache/apt/archives, go create space. For machine wey get real /boot partition, apt clean no go free any space there at all, because the cache dey for another filesystem.
Now get the number wey you go use compare.
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)Compare the Avail column with the size of those two files. The initrd na the bigger one. The next kernel update need space for another pair wey get roughly that size, so if Avail smaller than the current initrd, the next update don already dey fail.
Find the kernel wey you dey run
uname -r
cat /var/run/reboot-required.pkgsuname -r dey print release string of the kernel wey dey memory now. Copy that string put for somewhere. Na that version you must not touch.
The second file dey exist only when package ask for reboot. If you see a linux-image line inside am, e mean say newer kernel dey installed for disk but e never dey use, because machine never reboot since the package land. Reboot before you clean if you fit. apt dey protect the kernel wey dey run and the newest one, so if you clean while old kernel dey run, one extra version go remain pinned pass wetin you need.
List kernel packages and check their states
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'The first field na dpkg state code. ii mean say package dey installed and configured. iF mean say package dey installed but e never finish configuration. Na exactly this one failed upgrade above leave behind. rc mean say package don remove but e still get configuration files for disk. E no dey use space for /boot and e safe to purge.
The second field tell you the kind package wey e be. Name wey get version inside am, like linux-image-6.8.0-64-generic, na one specific kernel. Name wey no get version, like linux-image-generic, linux-headers-generic or linux-generic, na meta package. E no contain kernel. E only depend on the newest versioned kernel, so apt upgrade fit bring new kernels in. If you remove meta package, machine no go dey receive kernel updates again, and nothing go warn you afterwards.
The families divide like this. linux-image-* hold the compressed kernel for /boot. linux-modules-* and linux-modules-extra-* hold the drivers under /lib/modules. linux-headers-* hold build headers under /usr/src. This mean say purging headers go free space for root filesystem, but e no go free /boot space. If your problem na full /boot partition, na the image packages you need find.
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/These two listings suppose match each other and also match the dpkg --list output. Directory for /lib/modules wey no get matching installed package na leftover from person wey delete files by hand.
How apt dey decide which kernels to keep
apt autoremove no go remove kernel wey e consider protected, and the protected set include the kernel wey dey run now. The retention policy don change between Ubuntu releases, so read am from your own machine instead of trusting any number wey somebody write down anywhere.
apt-config dump | grep -i -e neverautoremove -e versionedkernel
ls -l /etc/apt/apt.conf.d/01autoremove /etc/apt/apt.conf.d/01autoremove-kernelsAPT::NeverAutoRemove na the list of package name patterns wey apt autoremove no dey touch. APT::VersionedKernelPackages na the list of name prefixes wey apt first treat as versioned kernel packages. For releases wey dey generate /etc/apt/apt.conf.d/01autoremove-kernels, /etc/kernel/postinst.d/apt-auto-removal dey rewrite that file every time dem install kernel package, so editing am by hand no go achieve anything: the next kernel install go overwrite your edit. For releases wey the file no dey, apt dey apply the same protection internally. Either way, apt-config dump go show the rules wey dey active for your box, and na that output be the correct answer for your release.
Cleanup wey safe to run
sudo apt update
sudo apt autoremove --purge --dry-run--dry-run no dey change anything for disk, and e dey print exactly wetin the real run go remove. Read the list. Two things suppose make you stop. Meta package like linux-generic or linux-image-generic for the removal list mean say something mark am as automatic, and removing am go stop your kernel updates. The string from uname -r for the removal list mean say the kernel wey dey run no dey protected. That one no suppose happen, so investigate am before you continue.
If the list look correct, run am for real.
sudo apt autoremove --purge
df -h /bootThe --purge part deletes the leftover configuration together with the package. E free small extra space, and e keep dpkg --list free from accumulating rc lines. This make the next audit easier to read.
Then confirm say the boot menu don rebuild. Removing a kernel package runs update-grub for you, so the menu suppose reference only files wey still dey exist.
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*Every version for the first output must appear for the second one. If menu entry point to file wey don disappear, working server fit become one wey stop for the GRUB prompt. This na one way to VPS wey no go boot after kernel update, and e harder to fix from rescue console than to prevent am here.
Why apt autoremove sometimes no dey remove anything
apt autoremove only dey remove packages wey dem mark as automatic. This mean say dem install the packages as dependency for another thing. If you install kernel by yourself with apt install linux-image-6.8.0-40-generic, dem mark am as manual. autoremove no go ever touch am, no matter how old e don be.
apt-mark showmanual | grep -E '^linux-'Any versioned kernel for that output no dey visible to autoremove. Hand am back, using version strings from your own listing:
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runLeave the meta packages wey dem mark as manual. Dem suppose be manual because na you ask for dem.
Remove one named kernel on purpose
Sometimes you fit want make one specific version comot immediately instead of waiting for when policy allow am. Name the image package and make apt work out the remaining steps.
sudo apt purge linux-image-6.8.0-40-genericapt go first print the removal list before e do anything, because linux-modules-extra-* depend on the image package and dem must comot for the same transaction. This printed list na your real safety check. Na here you go catch if dem dey remove a meta package together with the version wey you intend to remove. Answer n if anything unexpected dey inside. After that, use sudo apt autoremove --purge to collect the module and header packages wey no get reason to remain again.
Why you no dey remove the kernel wey dey run
The kernel wey already dey memory go continue to run after dem delete its files, so e go look like say nothing spoil at first. The things wey the kernel never load na dem go fail. Purging linux-modules-$(uname -r) dey delete /lib/modules/$(uname -r)/, so the next module load go fail:
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericFirewall reload go fail from that point, and mounting filesystem type wey this kernel never touch since boot go fail too. Meanwhile, /boot/vmlinuz-$(uname -r) don disappear, so boot menu no longer show the kernel wey dey run, and the next reboot go land for another place. The machine still dey serve network traffic, but e don already become unbootable. Check uname -r against the removal list every time.
When /boot too full for apt to run at all
Na this state dey make people look for this page. apt autoremove need dpkg to first finish configuring the kernel package wey only configure halfway, and that step rebuild initramfs. But the /boot no get space. Break the loop by hand one time.
uname -r
ls -1 /boot/initrd.img-*Choose one initrd wey version no be the string uname -r give you, then delete only that file.
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grubEvery line get reason. The rm na deliberate exception wey make dpkg believe say file dey there, even though e no dey. apt --fix-broken install finish the configuration wey fail before, now wey initramfs get space. autoremove --purge then remove the package wey file you delete belong to, together with the other old versions. This make dpkg match the files wey dey for disk again. update-grub rebuild the menu from the files wey actually dey there. No reboot between rm and update-grub, because for that period the menu fit still point to the file wey you just delete. If dpkg complain say e dey interrupted, sudo dpkg --configure -a do the same repair as apt --fix-broken install.
Di same work for dnf systems
If your VPS dey run Fedora or one of the RHEL rebuilds like Rocky Linux, the method dey different. Debian and Ubuntu dey protect kernels with apt autoremove rules and leave the cleanup for you or for unattended-upgrades to trigger, but dnf enforces a count wey dem call installonly_limit. E automatically remove the oldest kernel as soon as new installation go pass that count. Use grep installonly_limit /etc/dnf/dnf.conf and man 5 dnf.conf read the value wey dey active, and use sudo dnf remove --oldinstallonly clear any existing backlog. The kernel wey dey run still dey protected. For the wider comparison between both package managers, see the dnf and apt command equivalents.
Make e no happen again
Cleanup wey depend on say you go remember am go fail one day, so put am inside the thing wey dey install the kernels. Open /etc/apt/apt.conf.d/50unattended-upgrades and find these keys. The file wey ship with the system don already contain dem as commented lines:
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";Remove the comment sign instead of adding another copy for the end. For apt configuration, the last assignment for a key na the one wey take effect. So duplicate fit make the file contradict itself and hide which value really dey apply. Check wetin the parser finally set, and monitor a run wey no change anything:
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logThe log na the proof. E record every run, so upgrade wey fail because space no dey enough go show for there long before anybody notice say the machine dey behind on patches. The remaining part of that configuration dey covered for automatic security updates for Ubuntu.
Before the next kernel arrive, get one number to check. Na the same pair of commands from the beginning of this guide:
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)If Avail no big well-well pass that file, the next kernel go fail exactly as we describe above. So fix am now, no be during the upgrade. This check worth one minute together with your other disk health checks for a VPS. E matter pass immediately before a release upgrade, because moving Ubuntu 24.04 to 26.04 installs a fresh kernel early for the process, and do-release-upgrade no go continue when /boot no get enough space. If your LTS server never receive that upgrade offer yet, na timing cause am, no be fault. Ubuntu dey hold LTS-to-LTS upgrades until the 26.04.1 point release ships, so you get known window to put /boot in order first.
FAQ
Why Ubuntu dey keep old kernels instead of deleting dem?
Because if one kernel no boot, you go get nothing else to select. Keeping the previous version mean say bad update fit recover from GRUB menu instead of provider rescue console. apt therefore dey protect some kernel packages from automatic removal, and e always include the one wey you dey run. Run apt-config dump | grep -i neverautoremove to see the exact patterns wey your release dey protect, because this policy don change between releases.
apt autoremove --purge safe to run for production server?
Yes, as long as you read the dry run first. Run sudo apt autoremove --purge --dry-run, wey no dey write anything, and check the list wey e print. Stop if e contain meta package like linux-generic or linux-image-generic, because removing any of dem go stop future kernel updates. Stop too if e contain the version string wey uname -r print. If none of dem show, the packages wey e wan remove na old kernels and orphaned dependencies.
apt autoremove no remove anything and /boot still full. Wetin I go do?
The old kernels almost certainly get manual mark, and autoremove only dey touch packages wey get automatic mark. Run apt-mark showmanual | grep -E '^linux-'. Any versioned kernel wey dey listed there na something wey somebody install by hand before. Mark am automatic with sudo apt-mark auto linux-image-<version> and run the dry run again, or purge that particular version directly with sudo apt purge linux-image-<version>.
I fit delete files from /boot by hand?
Only do am deliberately one time, when /boot full reach the point wey apt no fit configure the broken kernel package. Delete one initrd.img-<version> file wey its version no be the output of uname -r, then run sudo apt --fix-broken install, sudo apt autoremove --purge and sudo update-grub immediately. If you delete files without those follow-up steps, dpkg go record packages wey their files don disappear, and GRUB menu entries go still point to missing files. The machine go fail for its next reboot instead of failing immediately when you make the mistake.