GRUB 2: Linux Boot Loader Configuration and Custom Menu Entries
Learn how GRUB 2 boots Linux, how grub.cfg is generated, how to change defaults safely, and how to create custom boot-menu entries.
GRUB 2 is the second-generation GNU GRand Unified Bootloader. It is a boot loader: software started by system firmware that displays boot choices, loads a Linux kernel, or starts another operating system or boot loader.
GRUB runs between firmware and the operating system. In a traditional BIOS boot, firmware loads GRUB from a boot area on disk. In a UEFI boot, firmware loads a GRUB boot application from the EFI System Partition. GRUB then reads its configuration, presents a menu when appropriate, loads the selected kernel and initramfs (also called initrd), and transfers control to Linux. Distribution packaging and exact paths vary between BIOS and UEFI systems.
GRUB 2 supports both traditional BIOS booting and UEFI booting. The boot mode, partition layout, firmware settings, and distribution determine which files and commands are active.
How GRUB 2 Configuration Is Built
The file GRUB reads during boot is usually called grub.cfg. It is a generated runtime menu configuration, not normally a file that you edit by hand.
Most Linux distributions build grub.cfg from two sources:
/etc/default/grubcontains global settings such as the default entry, timeout, kernel parameters, and some visual options./etc/grub.d/contains ordered executable scripts. Each script prints part of the final GRUB configuration.
A generator combines these sources and writes grub.cfg. Editing a source file has no effect on the boot menu until the configuration is regenerated.
| Location | Purpose | Edit directly? | Notes by distribution |
|---|---|---|---|
/etc/default/grub | Global menu-generation settings | Yes, as a source file | Common on Debian, Ubuntu, Fedora-family, and similar systems |
/etc/grub.d/ | Scripts that emit menu sections | Yes, when customization requires it | Names and contents vary with installed packages |
/boot/grub/grub.cfg | Generated GRUB configuration | No | Common output path on Debian/Ubuntu-style systems |
/boot/grub2/grub.cfg | Generated GRUB configuration | No | Common on many Fedora/RHEL-style installations |
Finding the Correct Generator and Output Path
The correct command and output path depend on the distribution and boot setup. Inspect existing files and consult the documentation for the installed release before generating a new configuration.
| Distribution family | Preferred command | Typical output location | Verification step |
|---|---|---|---|
| Debian/Ubuntu-style | sudo update-grub | /boot/grub/grub.cfg | Review detected kernels, operating systems, and errors |
| Systems using the direct generator | sudo grub-mkconfig -o /boot/grub/grub.cfg | /boot/grub/grub.cfg | Confirm that this is the active path first |
| Many Fedora/RHEL-style installations | sudo grub2-mkconfig -o /boot/grub2/grub.cfg | /boot/grub2/grub.cfg | Check distribution documentation, especially on UEFI systems |
update-grub is a Debian/Ubuntu convenience wrapper. grub-mkconfig is the underlying-style generator used directly on many systems. Fedora/RHEL-family installations commonly use grub2-mkconfig, but command names and active paths can vary.
ls -l /boot/grub/grub.cfg /boot/grub2/grub.cfg 2>/dev/null
ls -l /etc/default/grub /etc/grub.d/
Global Settings in /etc/default/grub
/etc/default/grub is a shell-style settings file read while configuration is generated. Values must use valid syntax. Quoted values are important when a setting contains spaces or multiple words.
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE=menu
GRUB_CMDLINE_LINUX=""
GRUB_CMDLINE_LINUX_DEFAULT="quiet"
Default entry and timeout
GRUB_DEFAULT selects the default menu entry. A value such as 0 commonly selects the first top-level entry, but generated ordering can change. Some systems support a menu title, submenu path, or saved-entry behavior instead. Inspect the generated menu before relying on a numeric index.
GRUB_TIMEOUT controls how many seconds GRUB waits before booting the default entry. A negative value can disable automatic timeout behavior on configurations that support it. GRUB_TIMEOUT_STYLE, where supported, controls whether the menu is shown, hidden, or displayed with a countdown.
Kernel command-line options
GRUB_CMDLINE_LINUX supplies kernel parameters to Linux entries. GRUB_CMDLINE_LINUX_DEFAULT commonly supplies parameters for normal boots while excluding them from recovery entries, depending on the distribution's generator scripts.
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX="loglevel=3"
Kernel parameters affect early boot, hardware detection, logging, security, and storage. Add only options you understand, and preserve a known-good entry before testing a change.
Visual settings
Depending on distribution, installed theme packages, and firmware mode, GRUB settings can control graphics mode or resolution, colors, themes, and a background image. Use the variables and file locations supported by that distribution rather than copying settings from another system. A visual setting that is unsupported by the active GRUB build may be ignored or produce an unusable display.
Scripts in /etc/grub.d/
Executable files in /etc/grub.d/ print sections of grub.cfg. Their numeric filename prefixes determine processing order: lower numbers are processed earlier.
| Typical script | Typical ordering | What it generates | Availability and cautions |
|---|---|---|---|
00_header | Very early | Initial variables, environment, and menu-wide setup | Common, but implementation varies |
05_debian_theme | Early | Theme and visual settings on applicable Debian-family systems | Distribution-specific |
10_linux | Early-middle | Installed Linux kernel and recovery entries | Usually supplied by distribution packages |
20_linux_xen | After standard Linux entries | Xen-related Linux entries | Present only when relevant packages and support exist |
| memtest scripts | Varies | Memory-testing entries | Require an installed memtest package |
30_os-prober | Later | Entries discovered on other operating systems | May be absent, disabled, or restricted |
40_custom | Later | User-provided custom menu entries | Common place for local additions |
Exact names and availability vary by distribution and installed packages. A script without execute permission does not normally contribute output.
find /etc/grub.d -maxdepth 1 -type f -printf '%M %f\n' | sort
A separately created script such as 07_example is processed before 10_linux, while 12_example is processed afterward. This controls where its entries appear relative to generated Linux entries.
Automatic Operating-System Discovery
os-prober is a utility that searches storage devices for other bootable operating systems. A generator script with a name such as 30_os-prober can use its results to add entries for another Linux installation, Windows, or another supported system.
Many modern distributions disable or restrict automatic probing by default because mounting or examining other installations can have security and policy implications. Enable it only when appropriate for the machine and its security policy. After enabling it, regenerate the configuration and inspect the generated entries. Do not assume that every detected installation is safe to boot.
GRUB Disk and Partition Notation
Linux device names and GRUB device names use different conventions. Linux might identify the first partition on a disk as /dev/sda1. GRUB may identify the same location as (hd0,msdos1) for an MBR-partitioned disk or (hd0,gpt1) for a GPT-partitioned disk.
| Linux device example | GRUB example | Disk numbering | Partition numbering | Partition scheme |
|---|---|---|---|---|
/dev/sda1 | (hd0,msdos1) | hd0 means disk zero | 1 means partition one | MBR partition table |
| First partition on the first GPT disk | (hd0,gpt1) | Starts at zero | Starts at one | GPT partition table |
| Second partition on the second GPT disk | (hd1,gpt2) | hd1 means disk one | 2 means partition two | GPT partition table |
Modern GRUB notation uses gpt or msdos to show the partition-table type. Disk numbering begins at zero, but partition numbering begins at one. This differs from GRUB Legacy conventions, so old instructions should not be applied blindly.
Disk order can change when disks are added, removed, or presented differently by firmware. Use filesystem or partition UUIDs when practical. UUID means a persistent identifier for a filesystem or partition.
lsblk -f
blkid
Creating a Custom Boot-Menu Entry
A menuentry is a GRUB configuration block defining one selectable item. You can place custom content in /etc/grub.d/40_custom, or create a separate numbered executable script such as /etc/grub.d/12_custom_entry.
A menu entry commonly contains a descriptive label, a root-filesystem lookup, a kernel line, and an initramfs line. The kernel and initramfs paths must refer to files that GRUB can access from the selected root filesystem or boot partition.
menuentry 'Custom Linux' {
search --fs-uuid --set=root <filesystem-uuid>
linux /boot/vmlinuz-<version> root=UUID=<filesystem-uuid> ro
initrd /boot/initrd.img-<version>
}
Replace the placeholders with real values. The search command tells GRUB which filesystem to use as its root. The linux command loads the kernel and passes Linux parameters. The initrd command loads the initial RAM filesystem, which supplies early drivers and userspace needed before the real root filesystem is fully available.
Using a separate generator script
A generator script is a shell script that prints GRUB configuration. It normally begins with an interpreter line, prints a status message, and uses a heredoc to emit the menuentry block.
#!/bin/sh
exec tail -n +3 $0
menuentry 'Custom Linux' {
search --fs-uuid --set=root <filesystem-uuid>
linux /boot/vmlinuz-<version> root=UUID=<filesystem-uuid> ro
initrd /boot/initrd.img-<version>
}
The common 40_custom pattern uses the interpreter line and a command that skips the first lines of the script, allowing the remaining text to be printed as GRUB configuration. A separately designed generator can instead use a heredoc:
#!/bin/sh
echo "Generating custom entry"ncat <<'GRUB_ENTRY'
menuentry 'Custom Linux' {
search --fs-uuid --set=root <filesystem-uuid>
linux /boot/vmlinuz-<version> root=UUID=<filesystem-uuid> ro
initrd /boot/initrd.img-<version>
}
GRUB_ENTRY
The heredoc delimiter marks the beginning and end of literal output. Ensure the script emits valid menuentry text and has execute permission.
sudo chmod +x /etc/grub.d/12_custom_entry
Choose the numeric prefix deliberately. For example, 07_example is processed before 10_linux; 12_example is processed afterward. Then regenerate grub.cfg using the command appropriate for the system.
A Safe GRUB Change Workflow
- Inspect the current configuration, source files, installed kernels, filesystems, UUIDs, and both possible GRUB output paths.
- Back up the source file you plan to edit.
- Edit
/etc/default/grub,/etc/grub.d/40_custom, or a suitable custom executable script. Do not edit generated grub.cfg. - Regenerate the configuration with the correct distribution command and destination.
- Read the generator output. Look for detected kernels, recovery entries, other operating systems, warnings, and errors.
- Inspect the resulting grub.cfg or generated menu entries and confirm that a known-good Linux entry remains available.
- Keep recovery media, a rescue environment, or another recovery route available before rebooting.
- Reboot only after confirming that the intended default and a working fallback are present.
sudo cp -a /etc/default/grub /etc/default/grub.backup
sudo update-grub
On a system that requires explicit generation, use the verified destination instead:
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
Do not run both commands merely because both are available. Select the command and output path that match the installed distribution and active boot configuration.
Troubleshooting
A direct edit to grub.cfg disappears
Generated output is overwritten during updates. Move the change to /etc/default/grub or an appropriate /etc/grub.d/ source and regenerate.
The menu still shows old settings
The configuration may not have been regenerated, or it may have been written to the wrong path. Identify the active grub.cfg, run the correct generator, and inspect its output.
A custom entry is missing
Check execute permission, the numeric prefix, shell syntax, and whether the script actually emits valid menuentry text. Review the generated file after regeneration.
GRUB cannot find the kernel or initramfs
Check the filesystem UUID, GRUB root lookup, partition notation, and exact kernel and initramfs paths. Confirm that the files exist on the filesystem GRUB is searching.
Another operating system is absent
os-prober may be missing, disabled by policy, or unable to inspect the installation. Check distribution policy, enable probing only when appropriate, regenerate, and validate the result. A manual chainload or custom entry may be needed.
The wrong default entry boots
GRUB_DEFAULT may refer to an outdated index, title, or submenu path. Inspect generated entry names and order, then use the supported index, title, or saved-entry mechanism for that distribution.
The system becomes unbootable
Boot a known-good entry or recovery environment, restore the backed-up source files, regenerate the configuration, and verify it before rebooting again. A boot-critical kernel parameter, root reference, or generated configuration may be invalid.
Exam-Relevant Summary
- GRUB 2 sits between firmware and the operating system and loads a selected kernel or chains to another boot loader.
grub.cfgis generated output; normally edit its sources instead./etc/default/grubsupplies global settings, while executable scripts in/etc/grub.d/emit menu sections.- Use
update-grubon Debian/Ubuntu-style systems, or an explicitly verifiedgrub-mkconfig/grub2-mkconfigoutput path elsewhere. GRUB_DEFAULTselects the default,GRUB_TIMEOUTcontrols waiting time, and theGRUB_CMDLINE_LINUX*variables add kernel parameters.- GRUB disks start at zero; GRUB partitions start at one. GPT and MBR-style notation commonly appear as
gptandmsdos. - UUID-based lookup is usually more stable than relying on disk order.
- Custom entries require valid root lookup, kernel, and initramfs lines, and custom generator scripts must be executable.
- Always regenerate, review output, preserve a known-good entry, and keep a recovery route available.
For related fundamentals, review the Linux file structure, GPT partitions, Bash, and finding the full path of shell commands.