RED HAT ENTERPRISE LINUX
Modify the System
Bootloader
Modify the system bootloader
CIS126RH | RHEL System Administration 1
Mesa Community College
GRUB 2 (GRand Unified Bootloader version 2) is the bootloader used on all modern
RHEL 9 systems. It is responsible for loading the Linux kernel into memory at boot.
Administrators must be able to view and modify bootloader settings — adding kernel
parameters, changing the default boot entry, and setting a boot timeout — without
breaking the system. The critical rule: never edit GRUB configuration files
directly. Always use grubby or grub2-mkconfig
so changes survive kernel updates. These skills are tested on the RHCSA exam.
Learning Objectives
-
Explain the GRUB 2 architecture —
Describe how GRUB 2 boots RHEL, where configuration files live, and
why
/boot/grub2/grub.cfgmust never be edited directly -
Modify kernel parameters with grubby —
Use
grubbyto add, remove, and view kernel command-line parameters for the default and specific boot entries -
Set the default boot entry —
Use
grubby --set-defaultandgrub2-set-defaultto configure which kernel boots by default -
Regenerate the GRUB configuration —
Use
grub2-mkconfigto rebuildgrub.cfgfrom templates after making changes to/etc/default/grub
GRUB 2 Architecture
GRUB 2 uses a two-layer configuration system to separate editable settings from the generated boot configuration.
| File / Location | Purpose | Edit directly? |
|---|---|---|
/etc/default/grub |
Administrator settings: timeout, cmdline options, graphics mode | Yes — this is the file to edit for system-wide settings |
/etc/grub.d/ |
Script files that generate menu entries (40_custom for custom entries) | Yes — for custom boot entries |
/boot/grub2/grub.cfg |
The actual boot configuration read by GRUB at boot time | No — auto-generated; manual edits are overwritten |
/boot/loader/entries/*.conf |
BLS (Boot Loader Specification) per-kernel entries on UEFI systems | Use grubby instead of editing directly |
grub.cfg is auto-generated by grub2-mkconfig and
overwritten every time a new kernel is installed. Manual edits are silently
lost. Always use grubby or edit /etc/default/grub
and regenerate.
Viewing the Current GRUB Configuration
Before making changes, always inspect the current bootloader state.
# Show the default kernel and its parameters
$ grubby --default-kernel
/boot/vmlinuz-5.14.0-362.24.1.el9_3.x86_64
# Show the index number of the default entry
$ grubby --default-index
0
# Show full details about the default boot entry
$ sudo grubby --info=DEFAULT
index=0
kernel="/boot/vmlinuz-5.14.0-362.24.1.el9_3.x86_64"
args="ro crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
root="/dev/mapper/rhel-root"
initrd="/boot/initramfs-5.14.0-362.24.1.el9_3.x86_64.img"
title="Red Hat Enterprise Linux (5.14.0-362.24.1.el9_3.x86_64) 9.3"
# List all boot entries
$ sudo grubby --info=ALL
Adding Kernel Parameters with grubby
grubby is the recommended tool for modifying kernel parameters
on RHEL 9. Changes take effect at the next reboot.
# Add a parameter to the default kernel
$ sudo grubby --update-kernel=DEFAULT --args="quiet"
# Add multiple parameters at once
$ sudo grubby --update-kernel=DEFAULT --args="quiet splash"
# Add a parameter to a specific kernel (by path)
$ sudo grubby --update-kernel=/boot/vmlinuz-5.14.0-362.el9.x86_64 \
--args="net.ifnames=0"
# Add a parameter to ALL installed kernels
$ sudo grubby --update-kernel=ALL --args="net.ifnames=0"
# Verify the change was applied
$ sudo grubby --info=DEFAULT
args="ro ... rhgb quiet net.ifnames=0"
Most exam tasks ask to add a kernel parameter. The answer is always:
sudo grubby --update-kernel=DEFAULT --args="PARAMETER"
followed by verification with sudo grubby --info=DEFAULT.
Removing Kernel Parameters with grubby
The --remove-args flag removes specific parameters from a
kernel entry without affecting other parameters.
# Remove a single parameter from the default kernel
$ sudo grubby --update-kernel=DEFAULT --remove-args="quiet"
# Remove multiple parameters
$ sudo grubby --update-kernel=DEFAULT --remove-args="quiet splash"
# Remove a parameter from ALL kernels
$ sudo grubby --update-kernel=ALL --remove-args="rhgb"
# Common parameters to add/remove and why
| Parameter | Effect when present | Common use |
|---|---|---|
quiet | Suppresses most kernel messages at boot | Remove to see verbose boot messages for diagnostics |
rhgb | Shows graphical boot splash screen | Remove on servers for text boot output |
net.ifnames=0 | Disables predictable network interface names (eth0, eth1) | Add for compatibility with legacy scripts |
rd.break | Drops to a shell early in boot (before root mount) | Add temporarily for password recovery |
systemd.unit=rescue.target | Boots into rescue mode | Add temporarily to troubleshoot startup issues |
Setting the Default Boot Entry
When multiple kernels are installed, the default boot entry determines which one loads automatically after the timeout expires.
# Show all available boot entries
$ sudo grubby --info=ALL
index=0
kernel="/boot/vmlinuz-5.14.0-362.24.1.el9_3.x86_64"
title="Red Hat Enterprise Linux (5.14.0-362.24.1.el9_3.x86_64) 9.3"
index=1
kernel="/boot/vmlinuz-5.14.0-284.30.1.el9_2.x86_64"
title="Red Hat Enterprise Linux (5.14.0-284.30.1.el9_2.x86_64) 9.2"
# Set the default by kernel path
$ sudo grubby --set-default=/boot/vmlinuz-5.14.0-284.30.1.el9_2.x86_64
# Set the default by index number
$ sudo grub2-set-default 1
# Set back to the newest/highest-numbered kernel
$ sudo grub2-set-default 0
# Verify the new default
$ grubby --default-kernel
/boot/vmlinuz-5.14.0-284.30.1.el9_2.x86_64
$ grubby --default-index
1
/etc/default/grub: System-Wide Settings
This file contains variables that apply to all boot entries when
grub2-mkconfig regenerates grub.cfg.
$ cat /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
| Variable | Purpose |
|---|---|
GRUB_TIMEOUT | Seconds to wait at boot menu before booting default (0=immediate, -1=wait forever) |
GRUB_DEFAULT | Default entry: a number, "saved" (use grubenv), or kernel title |
GRUB_CMDLINE_LINUX | Kernel parameters added to ALL boot entries |
GRUB_TERMINAL_OUTPUT | console = serial/VGA; gfxterm = graphical |
GRUB_ENABLE_BLSCFG | true = use BLS per-kernel config files (RHEL 9 default) |
grub2-mkconfig: Regenerating grub.cfg
After editing /etc/default/grub, regenerate the boot configuration
with grub2-mkconfig. The output location differs by firmware type.
# Step 1: Edit the settings file
$ sudo vim /etc/default/grub
# Change GRUB_TIMEOUT=5 to GRUB_TIMEOUT=10
# Step 2: Determine firmware type (BIOS or UEFI)
$ ls /sys/firmware/efi 2>/dev/null && echo UEFI || echo BIOS
UEFI
# Step 3: Regenerate grub.cfg
# UEFI systems:
$ sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
Generating grub configuration file ...
Adding boot menu entry for EFI firmware configuration
Found linux image: /boot/vmlinuz-5.14.0-362.24.1.el9_3.x86_64
Found initrd image: /boot/initramfs-5.14.0-362.24.1.el9_3.x86_64.img
done
# BIOS/legacy systems:
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# Step 4: Verify timeout changed in grub.cfg
$ grep timeout /boot/grub2/grub.cfg
UEFI: /boot/efi/EFI/redhat/grub.cfg
BIOS: /boot/grub2/grub.cfg
Check with ls /sys/firmware/efi — if the directory exists, the system uses UEFI.
Changing the Boot Timeout
The boot timeout controls how long GRUB waits at the menu before booting the
default entry automatically. This is changed via /etc/default/grub.
# Step 1: View current timeout
$ grep GRUB_TIMEOUT /etc/default/grub
GRUB_TIMEOUT=5
# Step 2: Change the timeout (edit the file)
$ sudo sed -i 's/^GRUB_TIMEOUT=.*/GRUB_TIMEOUT=10/' /etc/default/grub
# Step 3: Regenerate grub.cfg
$ sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg # UEFI
# or:
$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg # BIOS
# Step 4: Verify
$ grep GRUB_TIMEOUT /etc/default/grub
GRUB_TIMEOUT=10
# Special timeout values
# GRUB_TIMEOUT=0 → boot immediately, no menu shown
# GRUB_TIMEOUT=-1 → wait forever, always show menu
# GRUB_TIMEOUT=5 → show menu for 5 seconds (default)
Temporary Boot Parameters: Editing at Boot Time
For one-time debugging or recovery, boot parameters can be edited interactively in the GRUB menu — changes apply only to that single boot.
- Reboot the system. At the GRUB menu, press e to edit the selected entry.
-
Find the
linuxline (the line starting withlinuxorlinuxefi) — this is the kernel command line. -
Navigate to the end of the line and add or remove parameters.
Common changes: remove
quietandrhgbfor verbose output; addrd.breakfor initramfs shell access. - Press Ctrl+X to boot with the modified parameters. The changes apply only to this one boot — they are not saved.
Edits made at the GRUB menu with e apply only to the current boot.
To make permanent changes, use grubby or edit
/etc/default/grub and regenerate.
Boot Loader Specification (BLS) Entries
RHEL 9 uses the BLS format — each installed kernel has its own configuration
file in /boot/loader/entries/. grubby manages these files.
# List BLS entry files
$ ls /boot/loader/entries/
2a8e3a24c82e4f7c8e123abc-5.14.0-362.24.1.el9_3.x86_64.conf
2a8e3a24c82e4f7c8e123abc-5.14.0-284.30.1.el9_2.x86_64.conf
# View a BLS entry file
$ cat /boot/loader/entries/2a8e*-5.14.0-362*.conf
title Red Hat Enterprise Linux (5.14.0-362.24.1.el9_3.x86_64) 9.3
version 5.14.0-362.24.1.el9_3.x86_64
linux /vmlinuz-5.14.0-362.24.1.el9_3.x86_64
initrd /initramfs-5.14.0-362.24.1.el9_3.x86_64.img
options ro crashkernel=1G-4G:192M,... rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap rhgb quiet
grub_users $grub_users
grub_arg --unrestricted
grub_class kernel
# When grubby --update-kernel --args is run, it modifies the "options" line above
# This is why grubby changes are persistent — the .conf file is updated
grubby vs grub2-mkconfig: When to Use Each
| Task | Use | Why |
|---|---|---|
| Add a kernel parameter to default kernel | grubby --update-kernel=DEFAULT --args= |
Modifies only the targeted kernel entry; no regeneration needed |
| Remove a kernel parameter | grubby --update-kernel=DEFAULT --remove-args= |
Same — surgical removal from the args string |
| Set the default boot entry | grubby --set-default= or grub2-set-default |
Updates grubenv; no regeneration needed |
| Change boot timeout | Edit /etc/default/grub then grub2-mkconfig -o |
GRUB_TIMEOUT is a global setting applied during regeneration |
| Add a parameter to all kernels (including future) | Add to GRUB_CMDLINE_LINUX in /etc/default/grub then regenerate |
New kernels installed by dnf will automatically inherit the parameter |
| Add a custom boot entry | Edit /etc/grub.d/40_custom then regenerate |
Custom entries are defined in the /etc/grub.d/ script files |
Bootloader Quick Reference
| Task | Command |
|---|---|
| Show default kernel path | grubby --default-kernel |
| Show default entry index | grubby --default-index |
| Show all boot entry details | sudo grubby --info=ALL |
| Show default entry details | sudo grubby --info=DEFAULT |
| Add parameter to default kernel | sudo grubby --update-kernel=DEFAULT --args="PARAM" |
| Add parameter to all kernels | sudo grubby --update-kernel=ALL --args="PARAM" |
| Remove parameter from default kernel | sudo grubby --update-kernel=DEFAULT --remove-args="PARAM" |
| Set default by kernel path | sudo grubby --set-default=/boot/vmlinuz-VERSION |
| Set default by index | sudo grub2-set-default INDEX |
| View grub.cfg timeout setting | grep timeout /etc/default/grub |
| Change timeout (edit source) | sudo vim /etc/default/grub → change GRUB_TIMEOUT |
| Regenerate grub.cfg (UEFI) | sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg |
| Regenerate grub.cfg (BIOS) | sudo grub2-mkconfig -o /boot/grub2/grub.cfg |
| Check firmware type | ls /sys/firmware/efi 2>/dev/null && echo UEFI || echo BIOS |
Common Mistakes
| Mistake | What goes wrong | Correct approach |
|---|---|---|
Editing /boot/grub2/grub.cfg directly |
Changes are silently overwritten the next time grub2-mkconfig runs or a kernel is updated | Use grubby for per-kernel changes; edit /etc/default/grub for global changes |
| Forgetting to run grub2-mkconfig after editing /etc/default/grub | Changes to /etc/default/grub have no effect — grub.cfg still contains the old values | Always run sudo grub2-mkconfig -o /boot/.../grub.cfg after any edit to /etc/default/grub |
| Using the wrong grub.cfg path for the firmware type | grub2-mkconfig succeeds but writes to the wrong file — GRUB ignores the changes | Check with ls /sys/firmware/efi: UEFI → /boot/efi/EFI/redhat/grub.cfg; BIOS → /boot/grub2/grub.cfg |
| Using --args= instead of --remove-args= when trying to remove a parameter | The parameter is added a second time instead of being removed | Use --remove-args="PARAM" to remove; --args="PARAM" only adds |
| Not verifying with grubby --info=DEFAULT after making changes | Typo in parameter name goes unnoticed until reboot causes unexpected behaviour | Always run sudo grubby --info=DEFAULT to confirm the args string looks correct |
| Setting GRUB_TIMEOUT=0 on a remote system without serial console | If boot fails, there is no opportunity to select an alternate kernel — system is unreachable | Keep GRUB_TIMEOUT at least 1-5 seconds on remote systems to allow manual entry selection |
Practical Scenario: Adding net.ifnames=0
The exam scenario: configure the system to use traditional network interface names (eth0, eth1) instead of predictable names (ens3, eno1).
# Step 1: Verify current kernel parameters
$ sudo grubby --info=DEFAULT
args="ro ... rhgb quiet"
# net.ifnames=0 is not present
# Step 2: Add the parameter to ALL kernels
$ sudo grubby --update-kernel=ALL --args="net.ifnames=0"
# Step 3: Verify it was added
$ sudo grubby --info=DEFAULT
args="ro ... rhgb quiet net.ifnames=0"
# Step 4: Reboot for the change to take effect
$ sudo systemctl reboot
# After reboot: verify the interface names changed
$ ip link show
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
Knowledge Check
Answer these before moving to the next slide.
- Why should
/boot/grub2/grub.cfgnever be edited directly? What should be used instead? - Write the command to add the kernel parameter
console=ttyS0to the default boot entry. - After adding the parameter in question 2, write the command to verify it was successfully applied.
- Write the two steps needed to change the GRUB boot timeout from 5 seconds to 15 seconds on a UEFI system.
- There are two kernels installed. Write the command to make the second kernel (index 1) boot by default.
- What is the difference between
grubby --update-kernel=DEFAULTandgrubby --update-kernel=ALL?
Knowledge Check — Answers
/boot/grub2/grub.cfgis auto-generated bygrub2-mkconfigand overwritten every time a new kernel is installed or grub2-mkconfig is run. Manual edits are silently lost. Usegrubbyfor per-kernel changes or edit/etc/default/gruband regenerate withgrub2-mkconfig.sudo grubby --update-kernel=DEFAULT --args="console=ttyS0"sudo grubby --info=DEFAULT— examine theargs=line in the output and confirmconsole=ttyS0appears.- (1)
sudo vim /etc/default/gruband changeGRUB_TIMEOUT=5toGRUB_TIMEOUT=15. (2)sudo grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg(UEFI) orsudo grub2-mkconfig -o /boot/grub2/grub.cfg(BIOS). Check withls /sys/firmware/efito determine which path to use. sudo grub2-set-default 1— also acceptsudo grubby --set-default=/boot/vmlinuz-VERSIONwith the full path of the second kernel shown bysudo grubby --info=ALL.--update-kernel=DEFAULTmodifies only the currently configured default boot entry — the single kernel that loads when the system boots without manual selection.--update-kernel=ALLapplies the change to every installed kernel entry, including older kernels and rescue entries — useful for parameters that should always be present regardless of which kernel is booted.
Key Takeaways
-
Never edit
/boot/grub2/grub.cfgdirectly — it is auto-generated. Usegrubbyfor per-kernel parameter changes (no regeneration needed). Edit/etc/default/grubfor global settings like timeout, then rungrub2-mkconfig -o /path/to/grub.cfgto regenerate. -
Add parameters with
grubby --update-kernel=DEFAULT --args="PARAM". Remove with--remove-args=. UseALLinstead ofDEFAULTto apply to every installed kernel. Verify every change withsudo grubby --info=DEFAULT. -
Set the default boot entry with
grub2-set-default INDEX. Index 0 is the newest kernel. Usegrubby --info=ALLto see all entries and their indices. Usegrubby --set-default=/boot/vmlinuz-VERSIONfor path-based selection that survives index reordering. -
UEFI and BIOS use different
grub.cfgpaths. UEFI:/boot/efi/EFI/redhat/grub.cfg. BIOS:/boot/grub2/grub.cfg. Check withls /sys/firmware/efi. Sending grub2-mkconfig to the wrong path produces no error but also no effect at boot.
Graded Lab
- Run
grubby --default-kernelandsudo grubby --info=DEFAULTto record the current default kernel and its parameters. Note the args= line as your baseline. - Add the kernel parameter
quietto the default entry if it is not already present (or addnet.ifnames=0as an alternative). Usesudo grubby --update-kernel=DEFAULT --args="PARAM". Verify withsudo grubby --info=DEFAULT. - Remove the parameter you added in the previous step using
sudo grubby --update-kernel=DEFAULT --remove-args="PARAM". Verify it is gone withsudo grubby --info=DEFAULT. - Check the firmware type with
ls /sys/firmware/efi. View the current timeout in/etc/default/grub. ChangeGRUB_TIMEOUTto a different value and regenerate grub.cfg with the correct path for your firmware. Verify withgrep timeout /boot/grub2/grub.cfgor the EFI equivalent. - If multiple kernels are installed, use
sudo grubby --info=ALLto list them. Usesudo grub2-set-default 1to make the second entry default, then verify withgrubby --default-index. Restore index 0 as the default. - Open
/boot/grub2/grub.cfgin a read-only viewer (less). Identify the generated stanza for the default kernel. Confirm it matches whatgrubby --info=DEFAULTshowed — do not edit this file.
"Modify the system bootloader."
Use grubby --update-kernel=DEFAULT --args= for kernel parameters.
Use /etc/default/grub + grub2-mkconfig for global settings.
Always verify with grubby --info=DEFAULT.