Configure the GRUB2 Bootloader on RHEL

Tested on RHEL 10.2 (Coughlan) — vm1.lab.example (BIOS firmware)
Package grub2-tools 2.12-46.el10_2
grubby 8.40-83.el10
Applies to RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora
Privilege sudo or root for bootloader changes and reboots
Scope GRUB2 boot flow on RHEL, BLS entries under /boot/loader/entries/, grubby for default kernel and kernel arguments, /etc/default/grub, grub2-mkconfig --update-bls-cmdline, one-time grub2-reboot, and recovery from bad parameters. Does not cover Debian or Ubuntu GRUB, manual root password recovery, or exhaustive grubby flag reference.
Related guides grubby command examples
Boot with old kernel
What GRUB files do
Reset root password on RHEL
RHCSA tutorial
IMPORTANT
This guide is RHEL-family specific. RHEL 10 stores boot entries as Boot Loader Specification (BLS) snippets and expects you to manage kernels with grubby, not with Debian-style update-grub. It does not walk through resetting the root password at the GRUB prompt—that belongs in reset root password on RHEL.

On RHEL 10, GRUB2 reads BLS snippets, loads a kernel and initramfs, and passes kernel command-line arguments to the running system. This walkthrough on vm1.lab.example uses grubby for everyday changes and /etc/default/grub plus grub2-mkconfig when you need distribution-wide defaults synchronized into every entry.


How GRUB2 Booting Works on RHEL

text
Firmware
GRUB2
Boot Loader Specification entry
Kernel + initramfs + kernel arguments
Term Meaning on RHEL
GRUB2 Bootloader that shows the menu, loads the kernel, and passes arguments
BLS Boot Loader Specification format; each kernel has a snippet under /boot/loader/entries/
Kernel entry One BLS file describing linux, initrd, and options for a installed kernel
grubby RHEL tool to list entries, set the default kernel, and edit kernel arguments
/etc/default/grub Distribution defaults such as GRUB_CMDLINE_LINUX and menu timeout

Package updates install new kernels and BLS snippets automatically. Your job is usually to pick the default entry and adjust options, not to hand-edit grub.cfg for every kernel change.


RHEL GRUB2 Quick Reference

Task Command
List kernels and entries grubby --info=ALL
Show default kernel grubby --default-kernel
Set default kernel grubby --set-default /boot/vmlinuz-VERSION
Add argument to all kernels grubby --update-kernel=ALL --args="parameter=value"
Remove argument grubby --update-kernel=ALL --remove-args="parameter"
One-time next boot grub2-reboot <index|title|id>
Running kernel arguments cat /proc/cmdline
Regenerate GRUB config grub2-mkconfig -o /boot/grub2/grub.cfg
Sync /etc/default/grub into BLS grub2-mkconfig -o /boot/grub2/grub.cfg --update-bls-cmdline

For additional grubby flags and title-based lookups, see grubby command examples.


Identify BIOS vs UEFI Boot

Firmware mode determines where the platform firmware looks first, but RHEL 10 regenerates the same main configuration path for routine administration.

Check firmware mode:

bash
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
output
BIOS

On this lab host firmware is legacy BIOS. On UEFI systems the same check prints UEFI.

Locate the active GRUB configuration:

bash
ls -l /boot/grub2/grub.cfg
output
-rw-------. 1 root root 7352 Aug  3 11:45 /boot/grub2/grub.cfg

On RHEL 10, write regenerated configuration to /boot/grub2/grub.cfg for both BIOS and UEFI. The UEFI stub under /boot/efi/EFI/redhat/ loads that file; do not replace the stub grub.cfg with grub2-mkconfig output.


Understand RHEL Boot Loader Specification Entries

BLS snippets live in /boot/loader/entries/:

bash
ls /boot/loader/entries/
output
23b7a5ba4a464d768c37c2b2990e7d06-0-rescue.conf
23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64.conf
23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64+debug.conf

A typical entry contains:

Field Role
title Menu label
version Kernel version identifier
linux Path to vmlinuz
initrd Path to initramfs image
options Kernel command line (root=, resume=, rhgb, and custom parameters)

Inspect one file:

bash
head -8 /boot/loader/entries/23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64.conf
output
title Red Hat Enterprise Linux (6.12.0-211.42.1.el10_2.x86_64) 10.2 (Coughlan)
version 6.12.0-211.42.1.el10_2.x86_64
linux /vmlinuz-6.12.0-211.42.1.el10_2.x86_64
initrd /initramfs-6.12.0-211.42.1.el10_2.x86_64.img $tuned_initrd
options root=/dev/mapper/rhel-root ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet 
grub_users $grub_users
grub_arg --unrestricted
grub_class rhel

Treat these files as output of package management and grubby, not the primary edit surface. For file layout background, see what GRUB files do.


List Installed Kernels and Boot Entries

grubby --info=ALL summarizes every BLS-backed entry:

bash
grubby --info=ALL
output
index=0
kernel="/boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64+debug"
args="ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
root="/dev/mapper/rhel-root"
initrd="/boot/initramfs-6.12.0-211.42.1.el10_2.x86_64+debug.img $tuned_initrd"
title="Red Hat Enterprise Linux (6.12.0-211.42.1.el10_2.x86_64+debug) 10.2 (Coughlan) with debugging"
id="23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64+debug"
index=1
kernel="/boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64"
args="ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
root="/dev/mapper/rhel-root"
initrd="/boot/initramfs-6.12.0-211.42.1.el10_2.x86_64.img $tuned_initrd"
title="Red Hat Enterprise Linux (6.12.0-211.42.1.el10_2.x86_64) 10.2 (Coughlan)"
id="23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64"
index=2
kernel="/boot/vmlinuz-0-rescue-23b7a5ba4a464d768c37c2b2990e7d06"
args="ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
root="/dev/mapper/rhel-root"
initrd="/boot/initramfs-0-rescue-23b7a5ba4a464d768c37c2b2990e7d06.img"
title="Red Hat Enterprise Linux (0-rescue-23b7a5ba4a464d768c37c2b2990e7d06) 10.2 (Coughlan)"
id="23b7a5ba4a464d768c37c2b2990e7d06-0-rescue"

Read index for menu ordering, kernel for the path you pass to grubby --set-default, and args for stored kernel parameters. The 0-rescue entry is the rescue kernel created at installation.


Check and Change the Default Kernel

Show which kernel boots by default:

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

Set the default to the installed production kernel path (adjust the version to match your host):

bash
sudo grubby --set-default /boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64
output
The default is /boot/loader/entries/23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64.conf with index 1 and kernel /boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64

Confirm the saved default:

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

Reboot to run the newly selected default, then verify the running kernel:

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

Use kernel paths rather than menu indexes when you script changes. Installing or removing kernels can reorder indexes. For booting a previous build after an upgrade, see boot with old kernel.


Select a Different Kernel for One Boot

Persistent default: grubby --set-default updates saved_entry in /boot/grub2/grubenv for every future boot until you change it again.

One boot only: pick another entry at the GRUB menu, or set next_entry with the BLS entry id (most stable), title, or index:

bash
sudo grub2-reboot 23b7a5ba4a464d768c37c2b2990e7d06-0-rescue

Indexes also work (grubby --info=ALL shows each index=), but installing or removing kernels can reorder them. Red Hat recommends id or title when you need a repeatable one-time boot target.

Inspect the environment block:

bash
sudo grub2-editenv /boot/grub2/grubenv list
output
saved_entry=23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64
menu_auto_hide=1
boot_success=0
boot_indeterminate=0
next_entry=23b7a5ba4a464d768c37c2b2990e7d06-0-rescue

saved_entry remains the normal default. next_entry applies only to the next boot, then GRUB clears it.

Clear a pending one-time boot without rebooting:

bash
sudo grub2-editenv - unset next_entry

Add Kernel Command-Line Parameters

Use grubby for the everyday workflow. printk.time=1 adds timestamps to kernel log lines and is safe for lab testing:

bash
sudo grubby --update-kernel=ALL --args="printk.time=1"

Confirm the argument landed on every entry:

bash
grubby --info=/boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64 | grep ^args=
output
args="ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet printk.time=1"

The BLS options line matches:

bash
grep ^options /boot/loader/entries/23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64.conf
output
options root=/dev/mapper/rhel-root ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet printk.time=1

Reboot before the running kernel picks up new arguments:

bash
cat /proc/cmdline
output
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.12.0-211.42.1.el10_2.x86_64 root=/dev/mapper/rhel-root ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet

Until reboot, /proc/cmdline still reflects the currently running kernel, not the updated BLS entry.


Remove Kernel Parameters

Remove the test parameter from all kernels:

bash
sudo grubby --update-kernel=ALL --remove-args="printk.time=1"

Verify it disappeared from the stored entry:

bash
grubby --info=/boot/vmlinuz-6.12.0-211.42.1.el10_2.x86_64 | grep ^args=
output
args="ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"

Reboot and check /proc/cmdline again when you need to confirm the running kernel no longer has the parameter.


Configure Parameters Through /etc/default/grub

/etc/default/grub holds distribution-wide settings. Important keys on this host:

bash
grep -E '^GRUB_(TIMEOUT|DEFAULT|CMDLINE_LINUX)' /etc/default/grub
output
GRUB_TIMEOUT=5
GRUB_DEFAULT=saved
GRUB_CMDLINE_LINUX="resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
Setting Role
GRUB_CMDLINE_LINUX Distribution-wide kernel command line that grub2-mkconfig --update-bls-cmdline can push into the BLS entries
GRUB_TIMEOUT Seconds the menu waits before booting the default
GRUB_DEFAULT=saved Default entry comes from saved_entry in grubenv

grubby edits existing BLS options directly. /etc/default/grub holds distribution-wide defaults that grub2-mkconfig --update-bls-cmdline can overwrite into every BLS options line.

Add a shared argument to /etc/default/grub:

bash
sudo sed -i 's/rhgb quiet"/rhgb quiet audit=1"/' /etc/default/grub

Push GRUB_CMDLINE_LINUX into every BLS entry:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg --update-bls-cmdline
output
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done

Check one entry:

bash
grep ^options /boot/loader/entries/23b7a5ba4a464d768c37c2b2990e7d06-6.12.0-211.42.1.el10_2.x86_64.conf
output
options root=/dev/mapper/rhel-root ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet audit=1

Revert the test change on a lab host when finished:

bash
sudo sed -i 's/ audit=1//' /etc/default/grub

Regenerate so BLS entries drop the test argument:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg --update-bls-cmdline

Use grubby for routine kernel-argument changes directly in BLS entries. RHEL 10 normally carries those arguments forward when a newer kernel is installed. Use /etc/default/grub plus --update-bls-cmdline when you intentionally want the BLS command lines realigned with GRUB_CMDLINE_LINUX. That step overwrites BLS snippets; it is not merely appending missing arguments, so grubby-only parameters absent from GRUB_CMDLINE_LINUX can be removed.


Change the GRUB Menu Timeout

Edit GRUB_TIMEOUT in /etc/default/grub, then regenerate:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
output
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done

Confirm at the next boot that the menu waits the configured number of seconds. GRUB_TIMEOUT=0 hides the menu immediately unless you interrupt boot.


Inspect the Active Kernel Command Line

The running kernel exposes the command line it received at boot:

bash
cat /proc/cmdline
output
BOOT_IMAGE=(hd0,gpt2)/vmlinuz-6.12.0-211.42.1.el10_2.x86_64 root=/dev/mapper/rhel-root ro resume=UUID=78531da6-a389-46e8-9bad-267572940826 rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet

Compare this line to grubby --info or the BLS options field. If they differ, you likely changed stored entries but have not rebooted yet, or a one-time menu edit overrode the saved entry.


Rebuild GRUB Configuration

You do not need grub2-mkconfig after every grubby change. grubby updates BLS snippets and grubenv directly.

Regenerate when you change /etc/default/grub, after some manual recovery steps, or when generated grub.cfg is clearly stale:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
output
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done

On RHEL 10 the correct target is always:

bash
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

for BIOS and UEFI. Add --update-bls-cmdline when GRUB_CMDLINE_LINUX or other defaults must flow into /boot/loader/entries/.


Recover from a Bad Kernel Parameter

If a new kernel argument prevents boot:

  1. Interrupt the GRUB menu at startup.
  2. Highlight the entry and press e to edit temporarily.
  3. Remove or fix the bad argument on the linux line.
  4. Press Ctrl+x to boot with the temporary change.
  5. After the system is up, remove the argument permanently with grubby:
bash
sudo grubby --update-kernel=ALL --remove-args="bad.parameter"

Reboot again to confirm clean startup.

This workflow fixes kernel command-line mistakes. Locked root accounts or forgotten passwords use a different procedure in reset root password on RHEL.


Troubleshoot GRUB and Kernel Entries

Symptom Likely cause Fix
New kernel missing from menu Package did not finish installing or BLS snippet missing rpm -q kernel; reinstall kernel package; check /boot/loader/entries/
Wrong kernel boots every time Default not updated or saved_entry stale grubby --set-default /boot/vmlinuz-VERSION; verify grubby --default-kernel
Parameter in BLS but not active No reboot after grubby change Reboot; compare grubby --info to /proc/cmdline
Boot failure after parameter change Bad kernel argument Edit once at GRUB menu; remove with grubby --remove-args
BLS entry missing Manual deletion or failed install Reinstall kernel or rescue package; avoid hand-editing as routine
grub.cfg looks wrong Regenerated wrong path or stale file grub2-mkconfig -o /boot/grub2/grub.cfg; never overwrite UEFI stub directly
UEFI boot breaks after mkconfig Output written to EFI stub path Regenerate only /boot/grub2/grub.cfg on RHEL 10
Rescue kernel confusion 0-rescue is fallback, not default Use for recovery; set normal default with grubby --set-default after fix

Practical GRUB Configuration Examples

Safe patterns on a lab host:

  1. grubby --info=ALL — inventory kernels before you change anything
  2. grubby --set-default /boot/vmlinuz-VERSION — pick the production kernel
  3. grubby --update-kernel=ALL --args="printk.time=1" — test parameter add
  4. Reboot and cat /proc/cmdline — confirm the running kernel
  5. grubby --update-kernel=ALL --remove-args="printk.time=1" — revert
  6. Edit GRUB_TIMEOUT in /etc/default/grub, then grub2-mkconfig -o /boot/grub2/grub.cfg
  7. grub2-reboot 23b7a5ba4a464d768c37c2b2990e7d06-0-rescue — one-time rescue boot by BLS id; clear with grub2-editenv - unset next_entry

Avoid parameters that disable storage, networking, or SELinux unless you have snapshot recovery. Do not use this article as a root password reset guide.


References


Summary

You configured GRUB2 on RHEL by working with BLS snippets under /boot/loader/entries/ rather than treating grub.cfg as the primary edit target. grubby lists entries, sets the default kernel, and adds or removes kernel arguments on one or all installed kernels. grubby --default-kernel and uname -r confirm default selection after reboot; cat /proc/cmdline shows what the running kernel actually received.

The distinction that saves time on RHEL 10 is tooling choice: routine per-kernel work stays in grubby, while /etc/default/grub plus grub2-mkconfig -o /boot/grub2/grub.cfg --update-bls-cmdline synchronizes distribution-wide GRUB_CMDLINE_LINUX values into every BLS entry. Regenerate /boot/grub2/grub.cfg on both BIOS and UEFI; do not overwrite the UEFI stub configuration directly.

If a bad parameter blocks boot, edit once at the GRUB menu, boot, then make the fix permanent with grubby. For exhaustive command coverage, continue with grubby command examples; for booting a previous kernel build, see boot with old kernel. Root password recovery stays in reset root password on RHEL.


Frequently Asked Questions

1. Should I edit /boot/loader/entries by hand on RHEL 10?

No for routine work. grubby updates individual or all BLS snippets safely. Manual edits are easy to get wrong and are not the supported workflow when packages install new kernels.

2. When do I need grub2-mkconfig on RHEL 10?

Use grub2-mkconfig when you change /etc/default/grub settings such as timeout or GRUB_CMDLINE_LINUX and want those values pushed into BLS entries with --update-bls-cmdline. grubby alone is enough for per-kernel arguments and default kernel changes without regenerating grub.cfg.

3. What is the difference between grubby and editing /etc/default/grub?

grubby changes specific BLS entry options or the saved default kernel immediately. /etc/default/grub holds distribution-wide defaults that grub2-mkconfig can synchronize into every BLS entry when you pass --update-bls-cmdline.

4. How do I boot a different kernel for one reboot only?

Use the GRUB menu at boot, or run grub2-reboot with a BLS entry id, title, or index before rebooting. grub2-reboot sets next_entry in grubenv; the saved default kernel stays unchanged after that boot.

5. Where do I regenerate GRUB configuration on RHEL 10 UEFI systems?

Write to /boot/grub2/grub.cfg for both BIOS and UEFI. Do not overwrite the UEFI stub configuration under /boot/efi directly; the stub loads the main grub.cfg from /boot/grub2.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)