How to Configure GRUB to Default to Windows or Fedora

Set the default GRUB boot entry to Windows or Fedora using grub2-set-default and update the configuration.

The boot menu skips your preferred OS

You installed Fedora alongside Windows, or you just finished a major system update. The machine reboots and immediately drops into Windows. You want Fedora to load automatically, or you want the boot menu to stay on screen long enough to actually make a choice. The GRUB menu is either defaulting to the wrong entry or hiding entirely because the timeout is set to zero. You need a reliable way to tell the bootloader which operating system should load first, and you need that preference to survive kernel updates.

How GRUB decides what to boot

GRUB does not read a single static file to decide what loads next. It uses a two-step generation process. The template lives in /etc/default/grub. A collection of shell scripts in /etc/grub.d/ reads that template, scans your disks for operating systems, and writes the final configuration to /boot/grub2/grub.cfg. Every time you run grub2-mkconfig or install a new kernel, that final file gets overwritten.

This design means manual edits to grub.cfg disappear on the next update. Fedora provides two safe paths to change behavior. The grub2-set-default command writes a persistent preference to /boot/grub2/grubenv. The GRUB_DEFAULT variable in /etc/default/grub sets a fallback rule that survives config regeneration. You also control how long the menu waits using GRUB_TIMEOUT.

The grubenv file is a binary key-value store. GRUB reads it early in the boot process to check for a saved_entry variable. If that variable matches a menu entry title, GRUB boots that entry instead of the first one in the list. This mechanism is why grub2-set-default works without regenerating the config. The config file already contains the logic to check the environment file. You only need to update the environment file.

Fedora runs grub2-mkconfig automatically after kernel updates via package triggers. This keeps your boot menu in sync with new kernels. It also means you never need to manually rebuild the config after a routine dnf upgrade --refresh. You only rebuild when you change /etc/default/grub or add custom scripts to /etc/grub.d/.

Set the default boot entry

Find the exact name of the entry you want to boot. GRUB matches strings literally. A single space or a missing parenthesis will cause it to fall back to the first entry in the list.

sudo grep -i "menuentry" /boot/grub2/grub.cfg
# WHY: Lists every bootable option GRUB currently recognizes.
# WHY: The output shows the exact quoted strings you must use.
# WHY: UEFI systems may show "Windows Boot Manager" while BIOS shows "Windows 10".

Copy the exact string inside the quotes. Run the set-default command with that string.

sudo grub2-set-default "Fedora (43)"
# WHY: Writes the preference to /boot/grub2/grubenv.
# WHY: This file survives kernel updates and config regeneration.
# WHY: GRUB reads this environment file on the next boot to override the default.

If you want the change to apply immediately without rebooting, you can verify the environment file.

sudo grub2-editenv list
# WHY: Dumps the current GRUB environment variables.
# WHY: Confirms that the saved_entry matches your target OS.
# WHY: Shows the boot_indeterminate flag if GRUB is unsure of the last boot.

Adjust the boot menu timeout

The timeout controls how many seconds GRUB waits before auto-booting the default entry. A value of zero hides the menu entirely. A value of five gives you time to press Escape or Shift.

Edit the template file, not the generated config.

sudo nano /etc/default/grub
# WHY: Opens the user-modified template for GRUB configuration.
# WHY: Changes here persist across kernel updates and package upgrades.
# WHY: Always edit /etc/ files. Never touch /usr/lib/ or /boot/grub2/grub.cfg directly.

Locate the GRUB_TIMEOUT line. Change the number to your preferred wait time. If you want the menu to appear only when you press a key, set GRUB_TIMEOUT_STYLE=menu and keep GRUB_TIMEOUT=5. Save and exit.

Regenerate the configuration file. This step is mandatory. GRUB will not apply the new timeout until you rebuild the config.

sudo grub2-mkconfig -o /boot/grub2/grub.cfg
# WHY: Reads /etc/default/grub and /etc/grub.d/ scripts.
# WHY: Overwrites the live configuration at /boot/grub2/grub.cfg.
# WHY: UEFI systems may require -o /boot/efi/EFI/fedora/grub.cfg instead.

Check whether your system uses UEFI or BIOS to pick the correct output path. Run findmnt /boot/efi to verify. If it returns a mount point, use the UEFI path. If it returns nothing, stick with /boot/grub2/grub.cfg. The path mismatch is the most common reason timeout changes appear to do nothing.

Handle Windows updates that rename boot entries

Windows feature updates sometimes change the boot manager name or add a new recovery partition. GRUB scans the EFI system partition or the Windows BCD store and generates a new menu entry title. Your grub2-set-default string stops matching. GRUB silently falls back to the first entry.

You can avoid this by using a wildcard or an index number instead of a literal string. Index numbers start at zero. The first entry in the menu is 0, the second is 1, and so on.

sudo grub2-set-default 1
# WHY: Sets the default to the second entry in the generated menu.
# WHY: Index numbers ignore title changes caused by Windows updates.
# WHY: The index resets to zero if you add or remove OS entries.

Index numbers are stable as long as the menu order does not change. If you prefer a string that survives minor title variations, you can use a wildcard pattern. GRUB supports * and ? in the GRUB_DEFAULT variable, but grub2-set-default expects exact matches. For wildcard support, edit /etc/default/grub and set GRUB_DEFAULT="Windows*", then regenerate the config.

Verify the configuration

Reboot the machine and watch the boot sequence. The menu should appear for the number of seconds you configured. The default highlight should sit on your chosen operating system.

If you need to verify without rebooting, inspect the generated config file.

grep -E "set default|GRUB_TIMEOUT" /boot/grub2/grub.cfg | head -5
# WHY: Extracts the active default and timeout values from the live config.
# WHY: Confirms that grub2-mkconfig successfully applied your changes.
# WHY: head -5 prevents scrolling through hundreds of generated lines.

Reboot before you debug. Half the time the symptom is gone once the environment file and config are in sync.

Common pitfalls and what the error looks like

Editing /boot/grub2/grub.cfg directly is the most frequent mistake. The file contains a warning at the top: # DO NOT EDIT THIS FILE. The grub2-mkconfig command will erase your changes the next time a kernel updates. Always work in /etc/default/grub.

String mismatches cause silent failures. If you type grub2-set-default "Windows" but the actual entry is "Windows Boot Manager", GRUB ignores the saved entry and boots the first option in the list. You will see no error message. The system just boots the wrong OS. Run grep -i menuentry to copy the exact string.

UEFI path confusion breaks config regeneration. On UEFI systems, the bootloader lives under /boot/efi/EFI/fedora/. Running grub2-mkconfig -o /boot/grub2/grub.cfg on a UEFI machine writes to a dead file. The next boot ignores your changes. Check your firmware type first.

Timeout set to zero hides the menu. If GRUB_TIMEOUT=0 and GRUB_TIMEOUT_STYLE=hidden, you cannot interrupt the boot sequence. Change the timeout to at least three seconds. Press Shift or Escape during the POST screen to force the menu to appear.

Trust the package manager. Manual file edits drift, snapshots stay.

When to use this vs alternatives

Use grub2-set-default when you want to change the boot target without touching configuration files. Use GRUB_DEFAULT in /etc/default/grub when you want a permanent fallback that survives environment file resets. Use grub2-mkconfig when you change timeout values, add custom menu entries, or switch between BIOS and UEFI layouts. Use grubby when you need to modify kernel command line parameters or set default kernels without parsing GRUB syntax. Use efibootmgr when you want to change the boot order at the firmware level instead of relying on GRUB.

Where to go next