Linux online course

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/grub contains 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.

LocationPurposeEdit directly?Notes by distribution
/etc/default/grubGlobal menu-generation settingsYes, as a source fileCommon on Debian, Ubuntu, Fedora-family, and similar systems
/etc/grub.d/Scripts that emit menu sectionsYes, when customization requires itNames and contents vary with installed packages
/boot/grub/grub.cfgGenerated GRUB configurationNoCommon output path on Debian/Ubuntu-style systems
/boot/grub2/grub.cfgGenerated GRUB configurationNoCommon 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 familyPreferred commandTypical output locationVerification step
Debian/Ubuntu-stylesudo update-grub/boot/grub/grub.cfgReview detected kernels, operating systems, and errors
Systems using the direct generatorsudo grub-mkconfig -o /boot/grub/grub.cfg/boot/grub/grub.cfgConfirm that this is the active path first
Many Fedora/RHEL-style installationssudo grub2-mkconfig -o /boot/grub2/grub.cfg/boot/grub2/grub.cfgCheck 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 scriptTypical orderingWhat it generatesAvailability and cautions
00_headerVery earlyInitial variables, environment, and menu-wide setupCommon, but implementation varies
05_debian_themeEarlyTheme and visual settings on applicable Debian-family systemsDistribution-specific
10_linuxEarly-middleInstalled Linux kernel and recovery entriesUsually supplied by distribution packages
20_linux_xenAfter standard Linux entriesXen-related Linux entriesPresent only when relevant packages and support exist
memtest scriptsVariesMemory-testing entriesRequire an installed memtest package
30_os-proberLaterEntries discovered on other operating systemsMay be absent, disabled, or restricted
40_customLaterUser-provided custom menu entriesCommon 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 exampleGRUB exampleDisk numberingPartition numberingPartition scheme
/dev/sda1(hd0,msdos1)hd0 means disk zero1 means partition oneMBR partition table
First partition on the first GPT disk(hd0,gpt1)Starts at zeroStarts at oneGPT partition table
Second partition on the second GPT disk(hd1,gpt2)hd1 means disk one2 means partition twoGPT 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

  1. Inspect the current configuration, source files, installed kernels, filesystems, UUIDs, and both possible GRUB output paths.
  2. Back up the source file you plan to edit.
  3. Edit /etc/default/grub, /etc/grub.d/40_custom, or a suitable custom executable script. Do not edit generated grub.cfg.
  4. Regenerate the configuration with the correct distribution command and destination.
  5. Read the generator output. Look for detected kernels, recovery entries, other operating systems, warnings, and errors.
  6. Inspect the resulting grub.cfg or generated menu entries and confirm that a known-good Linux entry remains available.
  7. Keep recovery media, a rescue environment, or another recovery route available before rebooting.
  8. 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.cfg is generated output; normally edit its sources instead.
  • /etc/default/grub supplies global settings, while executable scripts in /etc/grub.d/ emit menu sections.
  • Use update-grub on Debian/Ubuntu-style systems, or an explicitly verified grub-mkconfig/grub2-mkconfig output path elsewhere.
  • GRUB_DEFAULT selects the default, GRUB_TIMEOUT controls waiting time, and the GRUB_CMDLINE_LINUX* variables add kernel parameters.
  • GRUB disks start at zero; GRUB partitions start at one. GPT and MBR-style notation commonly appear as gpt and msdos.
  • 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.