GRUB Bootloader Configuration and Recovery
GRUB2 (GRand Unified Bootloader 2) is the standard bootloader for Linux, responsible for loading the kernel and providing a boot menu for multi-boot systems. This guide covers GRUB2 configuration, menu customization, kernel parameter management, dual-boot setup, password protection, and recovery procedures for corrupted bootloaders on both BIOS and UEFI systems.
Prerequisites
- Linux system with GRUB2 installed (Ubuntu 20.04+, CentOS/Rocky 8+)
- Root access
- Understanding of your partition layout:
lsblkandblkid - For recovery: bootable live USB
GRUB2 File Locations and Structure
# Main configuration (auto-generated - do not edit directly)
/boot/grub/grub.cfg # Ubuntu/Debian
/boot/grub2/grub.cfg # CentOS/Rocky (BIOS)
/boot/efi/EFI/ubuntu/grub.cfg # Ubuntu UEFI
/boot/efi/EFI/rocky/grub.cfg # Rocky UEFI
# User-editable settings
/etc/default/grub # Main settings file
# Custom menu entries and scripts
/etc/grub.d/ # Scripts run to build grub.cfg
ls /etc/grub.d/
# 00_header - Global settings
# 05_debian_theme - Theme (Ubuntu)
# 10_linux - Linux entries (auto-detected)
# 30_os-prober - Detects other OSes (Windows, etc.)
# 40_custom - Your custom entries go here
# View current GRUB config
grep -v "^#" /etc/default/grub | grep -v "^$"
# Regenerate grub.cfg after any change
sudo update-grub # Ubuntu/Debian
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS/Rocky BIOS
sudo grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg # CentOS/Rocky UEFI
Customizing the Boot Menu
Edit /etc/default/grub for basic menu customization:
sudo nano /etc/default/grub
# Seconds to show menu (0=skip, -1=wait indefinitely)
GRUB_TIMEOUT=10
# Default entry (0=first, "saved"=last selected, or exact title)
GRUB_DEFAULT=0
# Save last selection as default
GRUB_SAVEDEFAULT=true
# Show menu even if only one OS (force menu display)
GRUB_TIMEOUT_STYLE=menu
# Disable quiet boot (show kernel messages)
GRUB_CMDLINE_LINUX_DEFAULT=""
# Set screen resolution (list available: videoinfo in GRUB console)
GRUB_GFXMODE=1920x1080
GRUB_GFXPAYLOAD_LINUX=keep
sudo update-grub
Add a custom menu entry:
sudo nano /etc/grub.d/40_custom
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.
# Boot from a specific kernel with custom parameters
menuentry "Ubuntu 22.04 (Debug Mode)" {
set root=(hd0,gpt2)
linux /boot/vmlinuz-5.15.0-100-generic root=/dev/sda2 ro debug ignore_loglevel
initrd /boot/initrd.img-5.15.0-100-generic
}
# Boot memtest86+ for RAM testing
menuentry "Memory Test (memtest86+)" {
linux16 /boot/memtest86+.bin
}
sudo update-grub
Kernel Parameters
Kernel parameters are passed via the linux line in GRUB. Set them persistently in /etc/default/grub.
sudo nano /etc/default/grub
# GRUB_CMDLINE_LINUX applies to all boots including recovery
# GRUB_CMDLINE_LINUX_DEFAULT only applies to normal boots
# Common parameters:
GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0"
# net.ifnames=0 biosdevname=0 = use old eth0/eth1 naming
# NVMe performance
GRUB_CMDLINE_LINUX="nvme_core.default_ps_max_latency_us=0"
# Disable spectre/meltdown mitigations for performance (test environments only!)
GRUB_CMDLINE_LINUX="mitigations=off"
# Set kernel console and serial
GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"
# Memory limit (for testing with limited RAM)
GRUB_CMDLINE_LINUX="mem=4G"
# IOMMU for VMs/PCI passthrough
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt"
sudo update-grub
# Reboot to apply
sudo reboot
# Verify parameters after reboot
cat /proc/cmdline
One-time kernel parameter (without saving):
- Boot to GRUB menu
- Press
eto edit the selected entry - Find the
linuxline, add parameters at end - Press
Ctrl+Xto boot with those parameters (not saved)
GRUB Password Protection
Protect GRUB from unauthorized editing or booting alternate entries:
# Generate encrypted password hash
grub-mkpasswd-pbkdf2
# Enter password twice
# Copy the resulting "grub.pbkdf2.sha512.10000...." hash
sudo nano /etc/grub.d/01_password
#!/bin/sh
cat << 'EOF'
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.YOURHASHHERE...
# Allow booting the default entry without a password
EOF
To allow specific entries without a password:
sudo nano /etc/grub.d/40_custom
menuentry "Ubuntu 22.04 LTS" --unrestricted {
# --unrestricted allows this entry to boot without password
...
}
sudo chmod +x /etc/grub.d/01_password
sudo update-grub
Dual-Boot Configuration
GRUB auto-detects other operating systems via os-prober:
# Install os-prober
sudo apt install os-prober # Ubuntu
sudo dnf install os-prober # CentOS/Rocky
# Enable os-prober in GRUB config (disabled by default in newer GRUB)
sudo nano /etc/default/grub
GRUB_DISABLE_OS_PROBER=false
# Run os-prober manually
sudo os-prober
# Output example: /dev/sda1@/EFI/Microsoft/Boot/bootmgfw.efi:Windows:Windows Boot Manager:efi
# Regenerate to include Windows
sudo update-grub
Manual Windows entry (if os-prober doesn't detect it):
sudo nano /etc/grub.d/40_custom
menuentry "Windows 11" {
insmod part_gpt
insmod fat
insmod chain
set root=(hd0,gpt1) # EFI system partition
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
sudo update-grub
Set Windows as default (if it's entry 2):
# Count from 0; check grub.cfg to find Windows entry number
grep "menuentry" /boot/grub/grub.cfg | cat -n
sudo nano /etc/default/grub
# Set: GRUB_DEFAULT=2 (or the Windows entry number)
sudo update-grub
GRUB Rescue Basics
If GRUB fails to load (shows grub rescue> prompt):
# In grub rescue> prompt:
# List available disks and partitions
ls
# Identify which has Linux boot files
ls (hd0,gpt2)/boot/
# Set root and prefix
set root=(hd0,gpt2)
set prefix=(hd0,gpt2)/boot/grub
# Load normal module
insmod normal
normal
# This brings up the GRUB menu
# Then boot normally and run update-grub to fix permanently
If in grub> prompt (more functionality available):
# List partitions
ls
# Boot Linux manually
set root=(hd0,2)
linux /boot/vmlinuz-5.15.0-100-generic root=/dev/sda2 ro
initrd /boot/initrd.img-5.15.0-100-generic
boot
Reinstalling GRUB
Boot from a live USB to reinstall GRUB on a failed system:
# Boot from Ubuntu live USB or similar
# Identify your partitions
lsblk
sudo blkid
# Mount the installed system
sudo mount /dev/sda2 /mnt # Root partition
sudo mount /dev/sda1 /mnt/boot # /boot (if separate)
# Bind mount virtual filesystems
sudo mount --bind /dev /mnt/dev
sudo mount --bind /dev/pts /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys /mnt/sys
# For UEFI: mount ESP
sudo mount /dev/sda1 /mnt/boot/efi # EFI System Partition
# Chroot into the system
sudo chroot /mnt /bin/bash
# Inside chroot - reinstall GRUB
# BIOS/MBR install
grub-install /dev/sda # Ubuntu
grub2-install /dev/sda # CentOS/Rocky
update-grub # Ubuntu
grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS/Rocky
# UEFI install
grub-install --target=x86_64-efi \
--efi-directory=/boot/efi \
--bootloader-id=ubuntu # Ubuntu
grub2-install --target=x86_64-efi \
--efi-directory=/boot/efi # CentOS/Rocky
# Regenerate config
update-grub # Ubuntu
grub2-mkconfig -o /boot/efi/EFI/rocky/grub.cfg # CentOS/Rocky
exit
# Back in live environment
sudo umount -R /mnt
sudo reboot
UEFI-Specific Configuration
# List EFI boot entries
sudo efibootmgr -v
# Output example:
# BootOrder: 0000,0001,0002
# Boot0000* ubuntu HD(1,GPT,...)/.../grubx64.efi
# Set boot order (boot entry 0000 first)
sudo efibootmgr -o 0000,0001,0002
# Delete a boot entry
sudo efibootmgr -b 0002 -B
# Add a new boot entry
sudo efibootmgr --create \
--disk /dev/sda \
--part 1 \
--label "Ubuntu" \
--loader /EFI/ubuntu/grubx64.efi
# Boot next reboot from specific entry (one-time override)
sudo efibootmgr --bootnext 0001
Secure Boot management:
# Check Secure Boot state
sudo mokutil --sb-state
# List enrolled keys
sudo mokutil --list-enrolled | head -20
# Import a new key (for custom kernel modules)
sudo mokutil --import my-key.der
Troubleshooting
GRUB shows "error: no such device" with UUID:
# UUID in grub.cfg doesn't match your disk
sudo blkid | grep UUID
# Update /etc/fstab and regenerate GRUB:
sudo update-grub
System boots to wrong OS after dual-boot setup:
# Check boot order
sudo efibootmgr # UEFI
# Set Linux GRUB entry first in boot order
sudo efibootmgr -o 0000 # Replace 0000 with your Linux entry
GRUB menu too brief to select (timeout too short):
sudo nano /etc/default/grub
# Set: GRUB_TIMEOUT=10
# Set: GRUB_TIMEOUT_STYLE=menu
sudo update-grub
"Minimal BASH-like line editing is supported" after install:
# GRUB loaded but can't find config
# In grub> prompt:
ls # Find partition with /boot/grub/
set root=(hd0,2)
set prefix=(hd0,2)/boot/grub
insmod normal
normal
# Then fix by reinstalling GRUB after booting
GRUB updates break UEFI boot after dist-upgrade:
# Reinstall GRUB to EFI
sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi --recheck
sudo update-grub
Conclusion
GRUB2 configuration is straightforward once you understand the relationship between /etc/default/grub, the /etc/grub.d/ scripts, and the auto-generated grub.cfg. Always modify settings through the appropriate files and run update-grub or grub2-mkconfig to regenerate the configuration. For recovery scenarios, the combination of the GRUB rescue prompt for temporary boots and a live USB for full reinstallation covers virtually any GRUB failure you'll encounter in production.


