Dual-boot Linux and Windows 10/11 on a UEFI PC today
On a modern PC, Windows and Linux do not chain-load each other through boot sectors any more. Both put their boot loader on the same EFI system partition (ESP), and the UEFI firmware keeps a list of boot entries: "Windows Boot Manager" and your Linux one (usually shim + GRUB). You choose a system from GRUB's menu, from the firmware's one-time boot menu, or with efibootmgr. The two things that cause trouble are BitLocker and boot order changes.
The 1997 "NT OS Loader + Linux" mini-HOWTO copied a Linux boot sector into a file and listed it in Windows NT's boot.ini, so NTLDR could start LILO. Windows Vista replaced boot.ini with the Boot Configuration Data store, and UEFI replaced boot sectors with files on the ESP. On a UEFI machine none of the old tricks are needed.
Before you install Linux
- Back up Windows and your files. Shrinking partitions is safe most of the time, not every time.
- Get your BitLocker recovery key if the Windows drive is encrypted. In an administrator Command Prompt run
manage-bde -protectors -get C:and write down the 48-digit recovery password, or check where your organization or Microsoft account stored it. Microsoft lists "changes to the boot manager" and "using PXE boot" among the events that can make BitLocker ask for this key at the next start. - Suspend BitLocker for the install:
manage-bde -protectors -disable C:(orSuspend-BitLocker -MountPoint Cin PowerShell). The drive stays encrypted; protection resumes automatically at the next Windows restart unless you set a reboot count. - Make room with Windows' own Disk Management tool ("Shrink Volume"). Leave the new space unallocated; the Linux installer will use it.
- Check the boot mode. Both systems must boot the same way, which today means UEFI. Windows' System Information shows "BIOS Mode: UEFI". Boot the Linux installer in UEFI mode too, not in a legacy/CSM mode.
- Leave Secure Boot on if your distribution supports it (Debian, Ubuntu, Fedora, RHEL and openSUSE ship a signed shim). Changing firmware security settings is the kind of change that can make BitLocker ask for its key, so do not toggle it without the key at hand.
Install Linux next to Windows
Most installers offer "install alongside Windows" and do the right thing. If you partition by hand:
- Reuse the existing ESP. Mount it at
/boot/efiand do not format it; it holds\EFI\Microsoft\Boot\bootmgfw.efi. Linux adds its own folder (\EFI\debian,\EFI\ubuntu,\EFI\fedora…) beside it. - Check the ESP's size with
lsblk. A small ESP is enough for GRUB and shim, but not for systemd-boot, which stores kernels there. With a small ESP, stay with GRUB. - Create the Linux root (and optionally swap) in the free space. See the Partition mini-HOWTO.
After installation, check the firmware entries from Linux:
$ sudo efibootmgr
BootCurrent: 0001
BootOrder: 0001,0000,2001
Boot0000* Windows Boot Manager
Boot0001* debian
Boot2001* EFI USB Device
Getting Windows into the GRUB menu
GRUB builds its menu with grub-mkconfig, which can run os-prober to find other operating systems. Since GRUB 2.06 (2021) this is off by default, because silently probing other disks and creating boot entries from what it finds is a possible attack route. Distributions differ (as of November 2026):
- Debian has followed upstream since Debian 12: os-prober does not run unless you turn it on.
- Ubuntu patches GRUB with an "auto" mode: os-prober runs on a new install, and later only if the previous menu already contained entries it found.
- Fedora and the RHEL family (RHEL, CentOS Stream, Alma, Rocky) revert the upstream change, so os-prober still runs by default, and their GRUB packages depend on it.
If Windows is missing from your menu, turn it on explicitly:
# Debian, Ubuntu
sudo apt install os-prober
echo 'GRUB_DISABLE_OS_PROBER=false' | sudo tee -a /etc/default/grub
sudo update-grub # should now report that it found Windows
# Fedora, RHEL family: check that /etc/default/grub does not set
# GRUB_DISABLE_OS_PROBER=true, then rebuild the menu
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
If you prefer not to run os-prober, add a fixed entry instead. Find the ESP's UUID with sudo blkid -s UUID -o value /dev/nvme0n1p1 (a short XXXX-XXXX value for FAT) and add this to /etc/grub.d/40_custom, below the existing lines:
menuentry "Windows Boot Manager" {
insmod part_gpt
insmod fat
insmod chain
search --no-floppy --fs-uuid --set=root XXXX-XXXX
chainloader /EFI/Microsoft/Boot/bootmgfw.efi
}
Then run sudo update-grub (or grub2-mkconfig as above). To make GRUB remember the last system you chose, set GRUB_DEFAULT=saved and GRUB_SAVEDEFAULT=true in /etc/default/grub.
systemd-boot needs none of this: it finds the Windows boot manager on the ESP automatically. Press w in its menu, or reboot into Windows from Linux with systemctl reboot --boot-loader-entry=ID, using the ID that bootctl list shows for Windows.
Choosing a system without GRUB
Every UEFI PC has a one-time boot menu, usually on F12, F11, F8 or Esc at power-on (it varies by maker). From Linux you can set the order or the next boot only:
sudo efibootmgr -o 0001,0000 # boot order: debian first, then Windows
sudo efibootmgr -n 0000 # boot Windows once, on the next restart only
sudo reboot # reboots now
The numbers are the BootXXXX values from efibootmgr output; yours will differ.
When Windows updates break the Linux boot
- The PC boots straight into Windows
- The Linux entry is still there but no longer first, or the firmware lost it. Boot Linux once from the firmware menu, then fix the order with
efibootmgr -o. If the entry is gone, boot a live USB and reinstall the boot loader as shown in the boot repair steps; that recreates the firmware entry. - A Secure Boot or "SBAT" violation message instead of the GRUB menu
- The firmware now refuses your installed shim or GRUB version, usually because a security update revoked older, vulnerable versions. Boot a current live USB of your distribution (its shim is newer), update the
shimandgrubpackages from the chroot, and reboot. Turning Secure Boot off only as a temporary step works too, but may trigger BitLocker recovery. - BitLocker asks for the recovery key
- Type the 48-digit recovery password. If it keeps asking, suspend and then resume BitLocker from within Windows; Microsoft notes that suspend and resume reseal the key without the recovery password.
The clock is wrong in one of the systems
Linux keeps the hardware clock in UTC; Windows keeps it in local time by default. After switching systems, the clock is off by your time-zone offset until it syncs. The Linux-side fix is:
sudo timedatectl set-local-rtc 1
The systemd documentation warns that local-time RTC mode "is not fully supported" and causes problems with time-zone and daylight-saving changes, so the better fix is to make Windows keep the hardware clock in UTC instead (a registry change on the Windows side) and leave Linux at the default, set-local-rtc 0.
Mistakes to avoid
- Installing Linux in legacy/BIOS mode next to a UEFI Windows. The two boot methods cannot see each other's boot loaders.
- Formatting the shared ESP during the Linux install. Windows will no longer start until you repair its boot files.
- Changing boot settings with BitLocker active and no recovery key at hand.
- Deleting the
\EFI\Microsoftfolder or the "Windows Boot Manager" entry while cleaning up withefibootmgr -B. Check the number twice.
The classic NT OS Loader + Linux mini-HOWTO is kept by the LDP at tldp.org. For choosing between boot loaders, see the LILO mini-HOWTO.
Sources
- GNU GRUB 2.14 release (NEWS: "Disable the os-prober by default" in 2.06; manual source on GRUB_DISABLE_OS_PROBER, search and chainloader), ftp.gnu.org
- Debian 12 release notes: GRUB no longer runs os-prober by default
- BitLocker recovery overview, Microsoft Learn
- BitLocker operations guide (protectors, suspend and resume), Microsoft Learn and manage-bde protectors (-disable and -rebootcount)
- ubuntu-os-prober-auto.patch, Ubuntu grub2 package and grub2 patch list (reverts "Disable the os-prober by default"), Fedora
- efibootmgr(8), Debian
- systemd-boot(7), bootctl(1) and systemctl(1), man7.org
- timedatectl(1), man7.org
- UEFI Secure Boot and shim, iPXE