I regularly have the need to try things out on Linux. Sometimes a virtual machine won't cut it for me typically due to memory, disk and performance limitations. Moreover, a decent, up-to-date, bootable Linux environment is a great backup in case all of my other computers are broken, infected or stolen. That entails having the Linux installation on an external, USB-attached hard disk drive which can boot with relative ease on any UEFI-enabled PC (driver compatibility notwithstanding). Moreover, all the preparatory work has to be performed using a single-boot Windows computer without ending up having a dual boot system. It sounds tough. It is tough, but I'm writing this from my portable Ubuntu Linux installation running off a USB-attached SSD!

What you need

  • An empty external (USB) hard drive. I used a USB 3 drive enclosure with a cheap 256Gb SSD. For those of you worrying about performance, the USB 3.0 port is faster than the maximum transfer rate of any SSD I've seen to this date.
  • Ubuntu Linux bootable USB drive. Very easy to create using Rufus on Windows. I used a cheap, promotional flash drive. Reduce, reuse, recycle FTW.
  • Windows System Repair Disc (a bootable USB drive with Windows recovery tools which you can make yourself) or a Windows installation or rescue CD-ROM / DVD-ROM. I used another promotional flash drive.

Remember to take backups of all your critical files and folders before continuing. You are going to make changes to your computer. If it breaks don't cry, I warned you. Also test both your bootable media. Twice. You will need them both!

Caveats

Having a dual- or multi-boot system isn't as straightforward as it used to be a decade ago. Nowadays, in the interest of security, performance and backwards compatibility, there are many semi-hidden options and features which can get in your way. Given enough experience and patience you can work around them. Below is a selection of problems that got me moderately stumped along the way.

Secure boot caveat

I have only tested these instructions with Secure Boot turned off. Even though Ubuntu does support Secure Boot (it comes with signed bootloaders) I have no idea if my method uses the signed bootloaders or not. I suggest turning off Secure Boot if possible.

FastBoot caveats

Many boards come with some sort of "fast boot" or "boot optimization" options. For example, my Intel NUC has an option called Fast Boot which won't let me choose an alternative boot device at startup. It also has an option to support Intel Rapid Start Technology which does get in the way of booting to multiple OS. I had to disable both.

It's worth noting that Windows 8 and 10 have an Fast Startup or Fast Boot feature. This feature takes some shortcuts when it comes to booting and also makes the NTFS filesystem remain in a dirty state, making it unwriteable from Linux. It's best to understand what it does and disable it if you plan on writing to your Windows drive from Linux.

USB host controller caveat

Some firmwares will present the USB host controller as UHCI (USB 1.1) at boot time. When Linux probes for an xHCI (USB 3) host controller during the boot process they will respond positively. At this time Linux loads the xHCI driver and the USB host controller resets itself.

However, your root filesystem is inside a device attached to this USB controller. Therefore the controller resetting means that Linux can no longer communicate with the USB-attached hard drive. Therefore the Linux boot will hang forever without any further indication as to what went wrong.

Most affected boards (including my Intel NUC) have an option to enable the xHCI host controller interface by default. Enabling the xHCI option in the BIOS fixes the hanging boot issue. If you are only using modern operating systems with USB 3 support (anything newer than and including Windows 8.1 and Ubuntu Linux 15.04) you can safely enable that option.

Installing Linux

Boot your computer from the Ubuntu Linux bootable USB drive. Remember that you may have to enter your computer's boot manager to do that (on my Intel NUC I have to press F10; on most other BIOS I've seen it's F9; consult your BIOS documentation).

Install Ubuntu Linux regularly. When it prompts you about the disk layout choose Something Else and partition your external HDD the way you want. I chose to create a modestly sized root partition (about 40Gb), a swap partition that's as big as the biggest RAM configuration I am going to be using this installation with plus one Gb (my computers max out at 16Gb so I made a 17Gb swap partition) and the rest of the disk went to a massive /home partition.

Caveat: I chose to use btrfs which – as I learned along the way – makes things a bit more complicated down the line. For your sanity's sake I recommend using ext4. This guide assumes the use of btrfs and will point out the caveats with this approach.

Fix Windows 10 boot

Unfortunately the Ubuntu Installer assumes that you want a dual booting configuration alongside Windows. Therefore it adds itself (actually, the bootloader it uses, GRUB2) to your computer's UEFI configuration. This causes two problems. For starters, the external HDD is not portable as you cannot boot with it on another computer.

Secondly, if you remove this external HDD your Windows won't boot. Bummer. We have to fix that.

  • Shut down your computer.
  • Disconnect the Ubuntu HDD
  • Boot from the Windows system repair disc USB drive (or a Windows installation or rescue CD-ROM / DVD-ROM).
  • Select Repair your computer.
  • Select the operating system and click Next.
  • Choose Command Prompt.
  • In the command prompt run
    diskpart
    sel disk 0
    list vol
  • Verify that the EFI partition is using the FAT32 file system. It will have a volume ID, let's say 99. Now we need to assign a drive letter to it. Back in the command prompt type:
    sel vol 99
    assign letter=z:
    exit
  • Now we need to fix the boot record. Again in the command prompt type:
    z:
    cd EFI/Microsoft/Boot
    bootrec /FixBoot
  • Finally, we need to re-create the BCD store which tells the Microsoft boot loader where to find Windows so it can boot it. From our trusted command prompt:
    ren BCD BCD.old
    bcdboot c:\Windows /l en-us /s z: All
  • If this didn't work try
    ren BCD BCD.old
    bootrec /RebuildBcd

At this point exit the command prompt and shut down your computer.

Create an ESP on the Ubuntu HDD

A hard drive is not bootable with UEFI unless it has an ESP (EFI System Partition). An ESP is simply a FAT32 partition with a special flag that tells the EFI BIOS to look inside it for boot information. We have to create one on your hard drive.

  • Plug in your external HDD and the Ubuntu Linux bootable USB stick.
  • Boot with the Ubuntu Linux bootable USB stick using the option to try Ubuntu before installing.
  • Open a Terminal (CTRL-ALT-T)
  • Run sudo fdisk -l to get a list of partitions.
  • Identify from them the drive that has the Linux partitions, in my case /dev/sdb. I'll call it /dev/sdX from now on.
  • Also identify the partition that contains the root filesystem. I will call it /dev/sdXY from now on.
  • Launch GParted from the Terminal:
    sudo gparted /dev/sdX
    Why not just click on GParted on your desktop? Well, I kept receiving errors about the Ubuntu Linux bootable USB stick because it was already in use. Of course it is, I am using it to run the computer off it, duh!
  • Resize the first partition on disk to have another 200 Mb of free space after it.
  • Create a new partition on the free space, changing the file system to fat32.
  • Apply operations. You need to do that now for the next step to be possible.
  • Right click the new partition.
  • Click on Manage Flags.
  • Set the boot and esp flags. This is what makes the partition "special" to the EFI BIOS.
  • One more thing! Note down the the partition that contains the ESP filesystem. I will call it /dev/sdXZ from now on.

Make sure the Ubuntu installation on the external HDD can see the ESP

The new ESP on the external drive must be visible by the Ubuntu installation in the HDD. Otherwise GRUB2, the Linux bootloader, won't be able to update itself, making your system unbootable after the next kernel update at the latest.

  • Launch GParted from the Terminal, as we saw above:
    sudo gparted /dev/sdX
  • Double click the partition with your Linux root (/) filesystem on the external HDD
  • Note down the UUID, e.g. 01234567-89ab-cdef-0123-4567890abcde
  • Double click the new FAT32 partition and note down the UUID, e.g. 0123-ABCD
  • Close GParted
  • Open a Terminal

The process is different depending on the format of your root partition on the external hard disk.

If you DID NOT use btrfs (e.g. you used ext4)

sudo umount /media/ubuntu/01234567-89ab-cdef-0123-4567890abcde 
sudo mount /dev/sdXY /mnt

If you DID use btrfs

If you DID use btrfs, you made your life complicated. We need to mount the btrfs subvolume containing the root partition instead of the entire partition. Otherwise you'll never be able to install GRUB and you'll probably lose an entire day, like me.

btrfs subvolume list /media/ubuntu/01234567-89ab-cdef-0123-4567890abcde

This will give you a line with a numeric ID. Let's say 123. Note it down.

umount /media/ubuntu/01234567-89ab-cdef-0123-4567890abcde
mount /dev/sdXY -o subvolid=123 /mnt

The rest of the instructions are common, no matter if used btrfs, ext4 or something else

  • sudo nano /mnt/etc/fstab
  • There is a line with /boot/efi already in this file. Comment it by placing a # in front of it.
  • Add the following line:
    UUID=0123-ABCD /boot/efi vfat defaults 0 1

Install GRUB2 on the external drive's EFI System Partition

Right now our external drive has an empty ESP. We need to put a bootloader in it to make it actually, well, bootable.

First caveat: all the instructions you find on-line assume you are using a dual boot system with Windows or macOS. When you have an external drive it is critical that you use the --removable option in the last step. This installs the EFI bootloader under the special "fallback path" EFI\Boot\bootx64.efi in the ESP. Normally this not supposed to be used for permanently installed Operating Systems. It's the mechanism used by EFI BIOS to boot arbitrary external media. Technically, that's exactly what our external hard drive is: arbitrary external media!

Second caveat: installing the bootloader is only possible from inside the Linux installation we want to boot. However, we need the bootloader to boot that installation, leading to a Catch-22 issue. The solution is to run the bootloader installation through a chroot jail. The actual caveat that got me stumped for a day comes from the fact that I am using btrfs (because it's so much better for SSDs!). btrfs has subvolumes. If you mount the entire partition instead of a subvolume the grub-install script can't figure out the mapping between paths and devices, therefore failing to install itself on the ESP, returning the cryptic error

/usr/sbin/grub-probe: error: cannot find a device for / (is /dev mounted?).

The error is misleading! /dev is mounted if you follow my instructions below. The actual problem, as I understand it, is that there is a discrepancy between the mounted device and the path to the chroot root. That's why I had you mount only the subvolume containing the root filesystem in the steps above. If you were not paying attention, you are not following the instructions step-by-step, you rebooted before this step or just came here directly looking for a solution to your problem about GRUB not installing look above for instructions on mounting the correct btrfs subvolume.

  • We need to prepare the chroot environment. The ESP must be mounted in the correct place and we have to bind system mount point for some special trees (most notably /dev). Moreover, we will copy the resolv.conf file to let the chroot environment have network access should it need it.
    mount /dev/sdXZ /mnt/boot/efi
    for i in /dev /dev/pts /proc /sys; do sudo mount -B $i /mnt/$i; done
    cp /etc/resolv.conf /mnt/etc/
    modprobe efivars
  • Finally we enter the chroot environment and install Grub in a way suitable for a removable device (see the first caveat above).
    sudo chroot /mnt
    grub-install -d /usr/lib/grub/x86_64-efi --efi-directory=/boot/efi/ --removable /dev/sdX

Now your external HDD is bootable. Reboot your computer, select it from the boot media selection of your UEFI BIOS and you're done!

201 comments

  • Hello. I followed all of your steps, but when I boot into Ubuntu, it shows "file /boot not found." Can you please help me? I looked up steps and it said I needed to include --boot-directory?
    • Are you using BTRFS instead of, say, EXT4? In this case you need to list the subvolumes and mount them. If your boot directory is a separate subvolume you have to mount it too. BTRFS always has subvolumes, even if you use one partition per volume. This cost me a day and some of my sanity as I explicitly say in the tutorial.

      Generally, remember to mount your /boot volume before mounting /boot/efi, in its turn happening before you enter a chroot environment to install GRUB to the external drive. If you mess it up GRUB will install its configuration files on the main volume (filesystem root, where the /boot mount point lives) which, of course, won't work properly since at boot time Linux will be mounting the boot volume to /boot, thus hiding any files in there.

      Also check your /etc/fstab file. If your /boot directory is on a different volume than your main (filesystem root) volume you need to have an entry there. Check that the UUID of the entry matches the reality of the partition table of your removable drive. The same applies for the EFI System Partition volume which also needs an fstab entry to mount point /boot/efi. I think that this is most likely what happened to you since you got a message about the /boot partition not being found by our friend GRUB.

      Only after doing all of that should you follow the last two steps of this tutorial. Then GRUB will be seeing all the partitions, mounted to our chroot environment, and the fstab will tell it how to find those partitions at boot time. The options we pass to GRUB will install an EFI boot loader on the external drive and that's all there is to it.
  • Thank you so much for the work you've put into this. I've had the same issue as Eric with the Windows fixboot 'access denied' error, and I'm definitely using the correct EFI partition (its the only fat32 partition of 100MB). But I'll deal with it by just reinstalling Windows 10 from scratch - thankfully I made a system image backup before starting this process.

    My (newbie) question is simpler: when preparing the chroot environment, how do I get from the ">" prompt, back to the normal terminal prompt? (Screenshot https://goo.gl/virUVq). Typing 'exit' didn't work. Thanks!
    • Check all your FAT32 partitions. Also note that they may not be in the first volume (physical device)! Many computers come with separate devices. Sometimes you have two separate devices even though you have installed only one hard disk if that hard disk is hybrid (an HDD and an SSD in one). While Windows sees it as one big drive, this is just a logical grouping; there are two physical devices and that's what matters when we try to get boot working ;)

      Regarding the chroot environment, pressing CTRL-D or typing exit should work. Please note that whenever you use sudo you get into a child shell so you have to exit this first. That is to say, if you chroot and then sudo you need to use exit twice to get back to the original shell you started from.
  • Hi there!
    Great tutorial.
    I want and will try this solution with a HDD plugged on Windows 10 laptop.
    My only doubt is that if when I install Ubuntu on the external HDD will Grub replace Windows 10 default bootloader/boot manager? Or in other words, will I always have the Grub menu instead of Windows 10 default bootloader/boot manager even when the HDD is not connected by usb to the laptop?
    My intention is not to have the Grub menu, that is, if I boot from the laptop disk, automatically boot Windows 10. And if I boot from the external HDD, automatically boot Ubuntu!
    Is that possible?
    At best, I would not mind that Grub menu only showing if booting from the external HDD, where Ubuntu is installed.
    Best regards,
    José Pedro
    • When you install Ubuntu it does replace Windows boot manager. That's why we have a tutorial section on recovering the Windows boot manager :)

      If you follow my instructions your laptop's internal drive will only have your Windows boot manager and only boot on Windows. The external HDD will have a special UEFI executable for GRUB2. This lets you plug it into any UEFI-capable computer (pretty much everything built after 2010 or thereabouts) and boot it - note that you may have to enter the boot selection menu if you haven't made boot from USB a higher priority item than boot from internal drive in the UEFI configuration (what we used to call "BIOS" back in the day).
      • Thanks for your answer.

        I'de also like to ask your opinion about I read in another article/tutorial, where the instructions are to install Ubuntu (from the live USB) opening the Terminal and run the following command:

        ubiquity --no-bootloader


        With this the author says the installation would not replace the Windows default bootloader.
        Is this accurate?

        Then the instructions (after Ubuntu is installed) are to boot from the live USB and use the GRUB console to look for the new installation, specifically look for the /boot/grub directory:

        grub> ls (hd2,gpt2)/boot/grub
        unicode.pf2 ...


        Then set this as the root for further commands:

        grub> set root=(hd2,gpt2)


        Then find out the UUID of the drive:

        grub> ls -l (hd2,gpt2)
                Partition hd2,gpt2: Filesystem type ext* 〈...snip...〉 UUID e86c20b9-83e1-447d-a3be-d1ddaad6c4c6 - Partition start at [...]


        After that tell GRUB where Linux is:

        grub> linux /boot/vmlinuz〈...tab here!...〉.efi.signed root=UUID=〈the UUID from above〉


        Finally set the initrd (initial RAM disk) and boot:

        grub> initrd /boot/initrd〈...tab here!...〉


        grub> boot


        What do you think about this solution?
        • Running ubiquity (the Live CD installer) like that will indeed NOT install GRUB at all. Anywhere. The rest of the instructions, however, don't make your external HDD bootable. If you read the original article over at Medium (side note: ALWAYS attribute sources, don't plagiarize) you'll see that his goal was to boot to Linux once and then change his EFI partition type, making an HDD that's only ever bootable on a Mac. With my instructions your HDD will be bootable on any computer with EFI and USB boot enabled, including but not limited to Macs (so far I've tried on a late-2011 MacBook Pro 15", late-2012 Mac Mini and an early-2015 MacBook Pro 13").

          To be precise, the rest of the instructions you posted from that article would have to be carried out every single time you want to boot to Linux. Yes, every single time you will have to insert the Live CD / Live USB, display its GRUB menu, drop back to the GRUB command prompt, mess with UUIDs and hopefully boot to Linux. This is the exact opposite to user-friendly. Also, it's highly unnecessary. Instead of these instructions just carry out my instructions from "Create an ESP on the Ubuntu HDD" onwards.

          Disclaimer: Follow this at your own risk. I have not tested this method. Your mileage may vary. If it breaks you get to keep both pieces ;)
  • Sorry for not having attributed the source of the information, but I'm not used to these things.

    I'll follow your instruction as soon has the external HDD arrives.

    My intention was to install Ubuntu on the external HDD, and whenever I wanted to boot to Ubuntu (always from the same PC) I'd only have to connect the HDD (in the UEFI/BIOS settings booting from the external HDD would have priority).
    I thought the process would be simpler, not that your instructions are complicated.

    Thank for the quick replies! :)
  • boot-repair could save you all the steps done with grub. All you need is the fat32 partition and fireup boot-repair, the rest explains the UI at the Advanced tap.
    • I had already tried that, unsuccessfully. That's why I went into the trouble of doing things manually and write it up. You can of course try your luck with boot-repair and if it fails just pout instead of using the free instructions someone posted on the Internet. But please don't come and shitpost on the comments. Nobody likes an arrogant know-it-all asshat. kthxbye
  • Hi when I run:
    for i in /dev /dev/pts /proc /sys; do sudo mount -B $i /mnt/$i; done
    I get:
    mount: mount point /mnt//dev does not exist
    mount: mount point /mnt//dev/pts does not exist
    mount: mount point /mnt//proc does not exist
    mount: mount point /mnt//sys does not exist
    Which makes me think I've done something wrong
    Also when I run:
    sudo chroot /mnt
    I get:
    chroot: failed to run command ‘/bin/bash’: No such file or directory
    Which makes me think I've made a mistake elsewhere in following the tutorial, any ideas on what I'm doing wrong?


    • Follow all my instructions from "Make sure the Ubuntu installation on the external HDD can see the ESP" onwards. Most likely you either forgot to mount the external drive under /mnt or the drive is formatted with the BTRFS file system for which I have added some very important warnings.
  • Hello,
    I followed all your steps. When I run last command
    grub-install -d /usr/lib/grub/x86_64-efi --efi-directory=/boot/efi/ --removable /dev/sdb

    I get this error:

    grub-install: error: /usr/lib/grub/x86_64-efi/modinfo.sh doesnn't exist. Please specify --target or --directory

    Filesystem is formated as ext4

    Any ideas?