Configuring and Fixing the GRUB Bootloader: From Kernel Parameters to the Rescue Shell
AI generated
$
/etc
Linux
GRUB Bootloader
Configure it, customize it, and fix it when it breaks

GRUB2 is the last piece of software standing between firmware and kernel on most Linux servers, yet it usually only gets touched once, during installation. Anyone who needs to set kernel parameters permanently, maintain a clean multi kernel setup, or get a server booting again after a failed update needs a solid grasp of /etc/default/grub, grub2-mkconfig, and the rescue shell.

10 min read Linux GRUB Bootloader

1. GRUB's role in the boot process

GRUB, short for Grand Unified Bootloader, is the piece of software that runs between firmware and kernel on both classic BIOS systems and UEFI systems. After the power on self test, the firmware either loads the Master Boot Record with the GRUB stage 1 code, or, on UEFI, loads the file grubx64.efi from the EFI system partition directly, handing control over to GRUB.

GRUB then loads its own configuration, optionally displays a menu with several kernel versions and boot options, and finally hands control to the selected kernel together with its initramfs. On a server without a physical monitor this step usually happens invisibly, but it remains just as critical: a broken GRUB setup blocks every boot, no matter how healthy the kernel and root filesystem themselves are.

A key distinction for understanding GRUB is the difference between the configuration source and the file actually read at boot time. Administrators almost never edit grub.cfg directly, but rather the templates in /etc/default/grub and /etc/grub.d, from which grub2-mkconfig generates the actual configuration file.

2. /etc/default/grub: the central configuration file

The file /etc/default/grub contains shell variables that are read by the scripts in /etc/grub.d. The most important ones are GRUB_DEFAULT for the default entry, GRUB_TIMEOUT for the menu wait time, GRUB_CMDLINE_LINUX_DEFAULT for kernel parameters in normal operation, and GRUB_CMDLINE_LINUX for parameters that should also apply in recovery mode.

On production servers a low GRUB_TIMEOUT makes sense since the menu is rarely operated manually anyway, while GRUB_TIMEOUT_STYLE=hidden only shows the menu when shift is held during boot, keeping the boot sequence visually clean. GRUB_DISABLE_OS_PROBER=true stops GRUB from scanning other partitions for foreign operating systems on every update, which on pure Linux servers only costs time and, in rare cases, creates incorrect entries.


# /etc/default/grub, a typical server configuration
GRUB_DEFAULT=0
GRUB_TIMEOUT=3
GRUB_TIMEOUT_STYLE=menu
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release 2>/dev/null || echo Debian)"
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
GRUB_DISABLE_OS_PROBER=true

3. Setting kernel parameters permanently through the bootloader

Kernel parameters meant to apply only to the current boot can be edited directly in the GRUB menu with the e key, but disappear again after a reboot. For permanent changes, such as cgroup parameters on container hosts, transparent_hugepage=never on database servers, or a specific IOMMU setting for PCI passthrough, the change belongs in GRUB_CMDLINE_LINUX_DEFAULT or GRUB_CMDLINE_LINUX.

After every change to /etc/default/grub, the configuration has to be regenerated before it takes effect on the next boot. Debian and Ubuntu use the wrapper update-grub, while RHEL based systems use grub2-mkconfig with an explicit target path. Forgetting this step is a common source of confusion when new parameters do not seem to apply despite a correct file.


# Debian/Ubuntu: regenerate the configuration
sudo update-grub

# RHEL/Alma/Rocky, BIOS system
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

# RHEL/Alma/Rocky, UEFI system
sudo grub2-mkconfig -o /boot/efi/EFI/almalinux/grub.cfg

# Check the active kernel parameters of the running system
cat /proc/cmdline

4. Customizing the boot menu: order, timeout, and hidden entries

The order of menu entries comes from the numerically sorted scripts in /etc/grub.d. The script 10_linux generates entries for installed kernels, and by default the newest kernel appears first and is preselected. With GRUB_DEFAULT=saved combined with grub-set-default, a specific entry can instead be pinned as the permanent default, independent of newly installed kernel versions.

For servers, a tidy menu matters more than visual extras: GRUB_TIMEOUT_STYLE=countdown shows only a countdown instead of the full menu, and GRUB_TERMINAL=console skips graphical elements, reducing the dependency on a working framebuffer configuration, which particularly helps with serial consoles and remote management through IPMI or iLO.

5. Managing multi kernel environments cleanly

On production systems, the previous kernel usually stays installed after an update so a rollback through the Advanced Options submenu in the GRUB menu remains possible in case of trouble. Debian and RHEL based distributions limit how many kernel versions get retained through the respective package manager, for example installonly_limit in dnf.conf on RHEL systems.

Anyone who deliberately wants to pin an older kernel as the default, for instance because a newer kernel causes driver problems with a RAID controller, can find the matching menu entry with grep against grub.cfg and then pin it permanently with grub-set-default, instead of selecting it manually in the menu on every boot.


# List available menu entries, including Advanced Options
grep -E "^menuentry|^submenu" /boot/grub2/grub.cfg

# Pin a specific entry as the permanent default (index or title string)
sudo grub2-set-default "Advanced options for AlmaLinux (10.0.99-original.el9.x86_64)"

# Check the currently saved default entry
sudo grub2-editenv list

6. Custom menu entries through 40_custom

Manual entries, for example a rescue image, a memory test, or an alternative kernel boot with special parameters for troubleshooting, belong in /etc/grub.d/40_custom or a dedicated executable file in /etc/grub.d. Direct edits to grub.cfg, on the other hand, get silently overwritten on every run of grub2-mkconfig and are lost.

A custom script in /etc/grub.d should start with a three digit number to control its position in the menu order, and must be executable, otherwise grub2-mkconfig skips it silently. This is a common source of confusion when a new entry does not show up in the menu after editing.


# /etc/grub.d/45_rescue_debug, a custom entry with an extra debug parameter
cat <<'EOF' | sudo tee /etc/grub.d/45_rescue_debug
#!/bin/sh
exec tail -n +3 $0
menuentry 'Kernel Debug Boot (systemd.log_level=debug)' {
    insmod gzio
    insmod part_gpt
    insmod xfs
    set root='hd0,gpt2'
    linux /vmlinuz root=/dev/mapper/vg-root ro systemd.log_level=debug
    initrd /initramfs.img
}
EOF
sudo chmod +x /etc/grub.d/45_rescue_debug
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

7. Recovery through the GRUB rescue shell

If the server ends up at a prompt reading grub> or grub rescue> instead of the menu, GRUB failed to load its configuration or important modules, usually because the reference to the boot partition is wrong or core.img got corrupted. In this minimal shell, ls reveals the available partition layout, and a manual set root followed by linux and initrd commands can still force a one time boot.

This manual boot is only a bridge for the current session and does not survive a reboot. What it does provide is enough time to log in to the running system and permanently repair the actual GRUB installation with grub2-install and grub2-mkconfig, instead of having to intervene manually on every boot.


# In the grub rescue shell: list available devices and partitions
grub rescue> ls
(hd0) (hd0,gpt2) (hd0,gpt1)

# Check and manually set the root partition and kernel path
grub rescue> ls (hd0,gpt2)/boot
grub rescue> set root=(hd0,gpt2)
grub rescue> set prefix=(hd0,gpt2)/boot/grub2
grub rescue> insmod normal
grub rescue> normal

8. grub-install and chroot repair from a live system

If the manual rescue shell is not enough, for example because core.img or the entire EFI system partition is damaged, the most reliable path is a live system or a rescue image from the hosting provider. There, the root partition and, on UEFI systems, the EFI system partition get mounted, essential virtual filesystems get bind mounted, and a chroot switches into the actual system.

Inside the chroot, grub2-install behaves exactly as it would on the running system itself, writing the boot code either into the MBR or creating a new grubx64.efi inside the EFI system partition along with a boot entry in the NVRAM firmware table. A final grub2-mkconfig run ensures the configuration matches the kernel that is actually installed.


# From the live system: mount the root partition and system paths
sudo mount /dev/mapper/vg-root /mnt
sudo mount /dev/sda1 /mnt/boot/efi
for fs in dev proc sys run; do sudo mount --bind /$fs /mnt/$fs; done
sudo chroot /mnt /bin/bash

# Inside the chroot: reinstall the bootloader
grub2-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=almalinux
grub2-mkconfig -o /boot/efi/EFI/almalinux/grub.cfg
exit

9. Best practices and common pitfalls

Before changing kernel parameters or the boot menu, it is worth testing through the provider's IPMI or rescue console, since a wrong root reference or a missing kernel module immediately leaves a remote server unreachable without physical access. A snapshot or backup before major GRUB changes is the cheapest insurance on virtualized servers.

Secure Boot adds another layer of complexity to manual grub-install calls, because the resulting EFI binary must be signed, otherwise the firmware refuses to start it. On systems with Secure Boot enabled, grub2-install should run through the distribution packages shim and grub2-efi rather than manually copying an unsigned binary.

After every kernel update it is worth a quick check with grep against grub.cfg to confirm the new kernel actually shows up as an entry and picked up the intended parameters from GRUB_CMDLINE_LINUX_DEFAULT, instead of blindly trusting the package manager's automatic flow.

Scenario Tool or command When to use it Risk if something goes wrong
Test a parameter for one boot only GRUB menu, e key One time test of a new kernel parameter Low, no reboot needed to undo it
Set a parameter permanently /etc/default/grub plus update-grub Production kernel parameters like cgroup options Medium, a wrong parameter can delay boot
Menu stuck at grub rescue grub rescue shell, manual set root Immediate boot without data loss in an emergency Temporary only, not a permanent fix
core.img or EFI partition damaged Live system, chroot, grub2-install Bootloader is fully broken High if the wrong device is targeted, verify the partition first
Pin a known good default kernel grub-set-default plus GRUB_DEFAULT=saved Known good kernel after update issues Low, reversible at any time

Mironsoft

Server administration, Docker hosts, and performance tuning

Linux servers nobody on the team really understands anymore?

We handle setup, hardening, and performance tuning of Linux servers and Docker hosts for Magento deployments, documented and traceable instead of grown and unclear.

Server Audit

Review the existing server configuration for security gaps and performance bottlenecks.

Docker Host Setup

Set up and secure production-ready Docker environments for Magento cleanly.

Monitoring & Tuning

Measure resource usage and tune systemd, kernel, and services with purpose.

10. Summary

GRUB Bootloader

Central file

/etc/default/grub, generates grub.cfg via update-grub or grub2-mkconfig

Permanent kernel parameters

Set them in GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub

Emergency tool

grub rescue shell for a one time manual boot without a reboot

Full repair

Live system, chroot, and grub2-install against the target partition

11. FAQ: GRUB Bootloader

1Where do I set kernel parameters permanently?
In /etc/default/grub, using GRUB_CMDLINE_LINUX_DEFAULT for normal operation or GRUB_CMDLINE_LINUX if the parameter should also apply in recovery mode. After editing, run update-grub or grub2-mkconfig, otherwise the change has no effect.
2Why doesn't my edit to grub.cfg survive the next update?
Because grub.cfg is a generated file, rebuilt from the templates in /etc/default/grub and /etc/grub.d every time grub2-mkconfig runs. Manual edits directly in grub.cfg get lost and belong in the source files or a custom script under /etc/grub.d instead.
3What does the grub rescue prompt mean?
GRUB failed to load its configuration or essential modules, usually due to an incorrect partition reference or a corrupted core.img. In this minimal shell, ls and set root can force a one time manual boot, but it does not survive a reboot.
4How do I permanently fix GRUB after an outage?
Boot a live system or rescue image, mount the root and EFI partitions, chroot into the system, and rerun grub2-install and grub2-mkconfig there. The bootloader is then correctly written back into the MBR or the EFI system partition.
5How do I keep several kernel versions available in parallel?
Distributions retain the previous kernel by default after an update and add an entry under the Advanced Options submenu. With grub-set-default, a specific kernel can be pinned as the permanent default, for example after driver issues with a newer version.
6How do I add a custom menu entry that survives updates?
Through a dedicated, executable file in /etc/grub.d with an appropriate number prefix, for example 45_rescue_debug, instead of editing grub.cfg directly. After creating it, make the file executable and rerun grub2-mkconfig.
7Why should I set GRUB_DISABLE_OS_PROBER to true?
On pure Linux servers without dual boot, it prevents unnecessary scans for foreign operating systems on every configuration run and avoids incorrect entries from misdetected partitions, especially in virtualized environments with many snapshot volumes.
8How does grub-install behave under Secure Boot?
The resulting EFI binary must be signed, otherwise the firmware refuses to boot it. On systems with Secure Boot enabled, installation runs through the distribution packages shim and grub2-efi instead of letting grub-install write an unsigned binary manually.
9Can I test kernel parameters without changing the configuration permanently?
Yes, in the GRUB menu the highlighted entry can be edited with the e key, adjusting the kernel line for exactly that one boot. After a reboot the change is gone again, which makes it ideal for risk free testing.
10How do I check which kernel parameters are actually active right now?
The command cat /proc/cmdline reads out the full kernel command line of the running system, regardless of whether the parameters came from GRUB_CMDLINE_LINUX_DEFAULT or were added manually in the menu.