Bootable USB Drive

How To Install Ubuntu on a USB Flash Drive#

The easiest way to run Ubuntu on a flash key is, of course, to download the Ubuntu ISO and use Startup Disk Creator. This process creates a bootable USB disk that has a read-only system drive with a writable overlay to make it feel like a “real” system. But doing so also has some significant limitations:

  1. It’s not possible to run Podman or Docker on an overlay root filesystem.

  2. Swap partitions are not automatically created (no hybernate/resume).

  3. You’re stuck with the default user (ubuntu)

  4. No disk encryption so you shouldn’t have SSH keys or login with Chrome

These are problems for me when I want a traveling disk to take to the classroom. Especially the last restriction. If I loose the drive I don’t want anyone to be able to boot the disk and have my browser ready to go with all of my passwords.

The solution is to create a VM that uses your USB disk as its root disk and go through the standard installation process in the VM. Once the process is complete you can simply remove the USB drive and boot it elsewhere.

But if it’s that simple, why a blog post? Because both virt-manager and VirtualBox make it impossible to use a USB drive as a disk in a VM. This is really not a common use case or even a good idea most of the time. So this is how to do it from the command line using qemu.

| ⚠️ Most cheap flash keys will not work! Linux puts too much pressure on them when used this way and they will quickly fail. Use an external hard drive.

  1. Plug in the device and find the drive mapping.

    $ sudo dmesg | grep "Attached SCSI"
    [250447.883828] sd 6:0:0:0: Attached scsi generic sg2 type 0
    [250447.921978] sd 6:0:0:0: [sdc] Attached SCSI removable disk
    
  2. Make sure that the drive is not mounted. You can use the “Eject” button in your file manager but also check using mount.

    $ mount | grep sdc 
    

    If there are any mounts shown use umount to unmount them:

    $ umount /dev/sdc1 
    
  3. Start the installer in a VM.

    $ sudo qemu-system-x86_64 \
        -bios /usr/share/ovmf/OVMF.fd -cpu host -accel accel=kvm \
        -drive file=/dev/sdc,format=raw \
        -cdrom ~/Downloads/ubuntu-22.04.1-desktop-amd64.iso \
        -m 4096 -smp 4 \
        -boot d
    

    Notes: The -boot d option boots from CDROM. The -bios option boots using UEFI, this will make the disk UEFI bootable. sudo is required to access the raw /dev/sdc device.

  4. After running the installer you can test your disk:

    $ sudo qemu-system-x86_64 \
        -bios /usr/share/ovmf/OVMF.fd -cpu host -accel accel=kvm \
        -drive file=/dev/sdc,format=raw \
        -m 4096 -smp 4 \
        -boot c
    

You can use the test mode to install and update software when you don’t want to reboot your computer. That’s it!

Boot Script#

Here’s a little shell script I put together so I could boot my external disk when it’s plugged in. If you use it make sure to replace the UUID of my volume with your own:

#! /bin/bash 

set -e 

device=$(sudo blkid | grep 7d1814cb-f5fb-42bc-b841-5c92c42f1d56 | perl -ne 's/^(\/dev\/sd.)\d/print($1)/e;')

if [ -z "$device" ]; then
	echo "Not plugged in."
	exit 1
fi

for devmount in $(mount | grep $device | cut -f1 -d' '); do  
	sudo umount $devmount
done 

sudo qemu-system-x86_64 \
	-bios /usr/share/ovmf/OVMF.fd \
	-cpu host \
	-accel accel=kvm \
	-drive file=${device},format=raw \
	-m 4096 -smp 4