Dual-boot Linux and Windows 10/11 on a UEFI PC today

Updated November 2026

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

Install Linux next to Windows

Most installers offer "install alongside Windows" and do the right thing. If you partition by hand:

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):

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 shim and grub packages 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

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