How to Safely Remove Old Kernels Using DNF or YUM

Deepak Prasad
Tested on Red Hat Enterprise Linux 10.2
Package dnf 4.20.0
Applies to RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora
Privilege sudo or root
Scope Remove excess distribution kernels with DNF or legacy YUM while keeping the running kernel and a tested fallback. Does not cover custom kernel builds, full GRUB administration, or APT kernel cleanup on Debian-family systems.
Related guides kernel-core update practices
change the default boot kernel
boot an older kernel with grubby
DNF4 vs DNF5
DNF cheat sheet

RHEL-family systems normally keep several kernel versions so you can boot an older build if a new one fails. When too many accumulate, use dnf remove --oldinstallonly to remove versions beyond the configured retention limit while preserving the running kernel.

Before removing anything, check both the running kernel with uname -r and the default boot kernel with grubby --default-kernel. Those two values are not always the same immediately after a kernel update.


Quick reference: remove old kernels safely

Task Command
Show running kernel uname -r
Show default boot kernel grubby --default-kernel
List installed kernels rpm -q kernel kernel-core | sort
List install-only packages dnf repoquery --installonly
Check /boot usage df -h /boot
Remove excess old kernels sudo dnf remove --oldinstallonly
Keep two versions for one DNF4 cleanup sudo dnf remove --oldinstallonly --setopt installonly_limit=2
DNF5: keep two versions sudo dnf remove --oldinstallonly --limit=2
Remove one specific non-running kernel sudo dnf remove kernel-core-VERSION
Legacy YUM systems sudo package-cleanup --oldkernels --count=2

--oldinstallonly is the normal DNF cleanup method. It follows install-only retention rules, and DNF protects the kernel you are running. Keep at least one tested fallback kernel beyond the rescue entry.


1. Check the running, default, and installed kernels

Start with the kernel currently loaded in memory:

bash
uname -r
output
6.12.0-211.42.1.el10_2.x86_64

See which kernel GRUB will boot after a reboot:

bash
grubby --default-kernel
output
/boot/vmlinuz-6.12.0-211.47.1.el10_2.x86_64

After a kernel update without a reboot, uname -r can still show the older build while grubby --default-kernel already points at the newer vmlinuz. Plan cleanup around both values, not just what is running right now.

List kernel packages installed on disk:

bash
rpm -q kernel kernel-core | sort
output
kernel-6.12.0-211.42.1.el10_2.x86_64
kernel-core-6.12.0-211.34.1.el10_2.x86_64
kernel-core-6.12.0-211.42.1.el10_2.x86_64
kernel-core-6.12.0-211.47.1.el10_2.x86_64

To see every install-only package DNF tracks, not only kernels:

bash
dnf repoquery --installonly --qf '%{name}-%{evr}.%{arch}' 'kernel*' | sort -u
output
kernel-6.12.0-211.42.1.el10_2.x86_64
kernel-core-6.12.0-211.34.1.el10_2.x86_64
kernel-core-6.12.0-211.42.1.el10_2.x86_64
kernel-core-6.12.0-211.47.1.el10_2.x86_64
kernel-modules-6.12.0-211.42.1.el10_2.x86_64
kernel-modules-core-6.12.0-211.34.1.el10_2.x86_64
kernel-modules-core-6.12.0-211.42.1.el10_2.x86_64
kernel-modules-core-6.12.0-211.47.1.el10_2.x86_64

If /boot space is tight, check usage before and after cleanup:

bash
df -h /boot
output
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2       2.0G  674M  1.3G  34% /boot

2. Understand installonly_limit

Kernel packages are install-only packages. Installing a new kernel normally adds another version instead of replacing the previous one.

See how many install-only versions DNF is configured to keep:

bash
grep '^installonly_limit' /etc/dnf/dnf.conf
output
installonly_limit=3
Value Meaning
3 Common default: newest kernel plus additional fallback versions
2 Keep fewer kernels but still retain a normal fallback
0 Unlimited install-only versions
1 Invalid as the persistent DNF retention value

Changing installonly_limit=2 in /etc/dnf/dnf.conf does not by itself delete kernels already on disk. Run an explicit cleanup when you need space now:

bash
sudo dnf remove --oldinstallonly

Current RHEL-family kernels may be split across packages such as kernel, kernel-core, kernel-modules, and kernel-modules-core. Let DNF remove the related set in one transaction.


3. Remove old kernels automatically with DNF

Standard DNF cleanup

dnf remove --oldinstallonly removes install-only packages above the effective retention limit. DNF skips the kernel you are running. Review the transaction before you confirm it:

bash
sudo dnf remove --oldinstallonly

When the installed count is already within the limit, DNF reports nothing to remove:

output
No old installonly packages found for removal.
Dependencies resolved.
Nothing to do.
Complete!

When excess versions exist, inspect the Removing: lines, any Removing dependent packages: section, Transaction Summary, and Freed space before answering y.

Keep only two versions for this cleanup

For DNF4, override the limit for one transaction without editing dnf.conf:

bash
sudo dnf remove --oldinstallonly --setopt installonly_limit=2

Persistent installonly_limit=1 is rejected on DNF4 (value 1 is not allowed).

DNF5

On Fedora and other DNF5 hosts, the same cleanup hook exists with a per-transaction limit:

bash
sudo dnf remove --oldinstallonly --limit=2

Run dnf remove --help on the target host before you script this. For broader DNF4 versus DNF5 differences, see DNF4 vs DNF5.


4. Remove one specific old kernel

When automatic cleanup is not the right tool, target a kernel that is neither the running kernel nor the default boot kernel. Check both values first, then select the older build you intend to remove.

List installed versions:

bash
rpm -q kernel kernel-core | sort

In this example, 6.12.0-211.34.1.el10_2 is the oldest build on disk. The running kernel is 6.12.0-211.42.1.el10_2, and grubby --default-kernel points at 6.12.0-211.47.1.el10_2.

Preview the transaction by targeting kernel-core. DNF should pull related module packages in the same removal:

bash
sudo dnf remove --assumeno kernel-core-6.12.0-211.34.1.el10_2.x86_64
output
============================================================================================
 Package               Arch    Version                Repository                        Size
============================================================================================
Removing:
 kernel-core           x86_64  6.12.0-211.34.1.el10_2 @rhel-10-for-x86_64-baseos-rpms   70 M
Removing dependent packages:
 kernel-modules-core   x86_64  6.12.0-211.34.1.el10_2 @rhel-10-for-x86_64-baseos-rpms   28 M

Transaction Summary
============================================================================================
Remove  2 Packages

Freed space: 97 M
Operation aborted.

When the preview looks right, run the same command without --assumeno and confirm.

Do not remove kernels by deleting files under /boot or by running rpm -e as the primary workflow. Use dnf remove so related packages stay aligned.


5. Why DNF refuses to remove the running kernel

Targeting the active kernel-core is blocked on purpose:

bash
sudo dnf remove --assumeno kernel-core-6.12.0-211.42.1.el10_2.x86_64
output
Error:
 Problem: The operation would result in removing the following protected packages: kernel-core

That protection is desirable. Remove a different build instead, or reboot into the kernel you intend to keep, verify it works, then remove the older non-running version.

Running-kernel protection is enabled by default (protect_running_kernel = 1 in dnf config-manager --dump on this host).


6. Why dnf autoremove does not replace kernel cleanup

dnf autoremove removes unused dependency packages. Install-only packages such as kernels use a separate retention mechanism and are not the target of normal autoremove processing.

bash
sudo dnf autoremove --assumeno
output
Dependencies resolved.
Nothing to do.
Complete!

For deliberate old-kernel cleanup, use:

bash
sudo dnf remove --oldinstallonly

That respects install-only package retention rules and protects the running kernel.


7. Remove old kernels with YUM on legacy systems

CentOS 7, RHEL 7, and other YUM-only hosts use package-cleanup from yum-utils:

bash
sudo yum install yum-utils

Then trim old kernels while keeping two versions:

bash
sudo package-cleanup --oldkernels --count=2

--count=2 keeps two kernel versions. To drop one specific build:

bash
sudo yum remove kernel-VERSION

On current DNF systems, package-cleanup is usually absent:

output
bash: package-cleanup: command not found

Use dnf remove --oldinstallonly on modern RHEL-family hosts. Do not mix package-cleanup into current DNF instructions.


8. Fix /boot full and kernel cleanup problems

Problem What to check
/boot is full df -h /boot, installed kernel count
No old installonly packages found Current count versus installonly_limit
--oldinstallonly not recognized dnf remove --help / DNF generation
Protected kernel-core error You selected the running kernel
GRUB still shows removed kernel grubby --info=ALL, BLS entries under /boot/loader/entries/
installonly_limit changed but nothing disappeared Run explicit dnf remove --oldinstallonly
Third-party kernel remains Remove ELRepo or other vendor RPMs separately

After cleanup, verify the running kernel, installed packages, /boot space, and default boot entry:

bash
uname -r

Confirm which kernel packages remain installed:

bash
rpm -q kernel kernel-core | sort

Check whether /boot freed space:

bash
df -h /boot

Verify the default boot entry still points at a valid kernel:

bash
grubby --default-kernel

Removing the RPM usually updates the boot entry too. If a stale menu item remains on BLS-based systems, inspect /boot/loader/entries/ before editing bootloader files by hand.


9. Prevent old kernels from accumulating

Set retention in /etc/dnf/dnf.conf (or /etc/yum.conf on legacy YUM hosts):

ini
installonly_limit=3

Use 2 only when you deliberately accept a smaller fallback window. Changing the file affects future installs; run dnf remove --oldinstallonly when you need immediate cleanup.

Use the package-manager retention mechanism rather than cron jobs that grep kernel RPMs and call rpm -e.

Before aggressive cleanup:

  • boot and test a new kernel before deleting known-good fallbacks
  • keep at least one tested normal fallback kernel
  • check uname -r and grubby --default-kernel
  • review the DNF removal transaction before passing -y
  • do not manually delete /boot kernel files

Summary

On current RHEL-family systems, sudo dnf remove --oldinstallonly is the normal way to trim excess distribution kernels. Legacy YUM hosts use sudo package-cleanup --oldkernels --count=2.

Before either operation, verify uname -r and grubby --default-kernel, and keep a tested fallback kernel you can boot if the newest build fails.


References

Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration