Boot Ubuntu Server 20.x from External USB SSD on Raspberry Pi4

This is a guide for configuring Raspberry Pi4 to boot Ubuntu from external USB SSD drive instad of SD card. SSD drives are much faster than SD cards, more reliabale and now lower cost than SD cards for larger memory sizes.
Instructions for Ubuntu server 20.10 and Ubuntu Server 20.04.1 are provided. Ubuntu 20.10 has the latest support for Raspberry Pi4 so I am using this for my projects until updates get added to the 20.04 LTS branch.

Table of Contents

    Requirements

    This guide assumes you are familiar with opertion of a Raspberry Pi, writing images to SD cards, and accessing the Raspberry Pi via SSH.
    Ubuntu Server 20.04.1 requires additional steps compared to Ubuntu Server 20.10.

    Hardware used in this guide

    • Raspberry Pi 4 with at least 2GB RAM
    • Any type of micro SD card with at least 8GB
    • Kingston A400 120GB SSD
    • StarTech SATA to USB adapter
    • Eluteng SATA to USB adapter
    • Adequate Power Supply due to additional SSD power consumption. (3.5A recommended)

    Software used:

    • Windows 10 PC however guide will be similar for MAC and Linux Users.
    • Raspberry Pi Imager (Balena Etcher is also a good tool for writing to SD cards)

    NOTE: It turns out that there are a lot of SATA to USB adapters that do not work correctly when used to boot the Raspberry Pi. After many lost hours trying to get an incompatible cable to work I found this great resource on this topic with a database of know working cables.

    James Chambers’ blog was also a great resource for writing other parts of this guide.

    1. Upgrade bootloader firmware on Raspberry Pi 4

    You need to make sure that the your Raspberry Pi 4 is running the latest bootloader firmware available. USB boot feature was enabled on the Pi 4 bootloader in the fall of 2020. Likely your Pi does not have the latest firmware so make sure not to skip this step. At this time it seems like you need to use Raspberry Pi OS to do modifications of the bootloader as third party OS support is limited. Instructions assume you are connected via Ethernet and are familiar with accessing Pi via SSH.

    1. Use Raspberry Pi Imager V1.4 to install Raspberry Pi OS (lite version without desktop is best) on SD card
    2. Copy empty text file called ssh.txt onto the system-boot partition of the SD card. Remove SD card from PC and insert into Raspberry Pi
    3. SSH into Pi
      Default user: pi
      default password: raspberry
    4. Make sure you have the latest kernal updates. This will take several minutes
      sudo apt update && sudo apt full-upgrade -y
    5. Restart Pi to apply updates
      sudo reboot
    6. SSH into Pi
    7. Your Pi may currently be configured to use critical or stable bootloader releases. Normally I configure it to use the stable releases. Open file and change the FIRMWARE_RELEASE_STATUS entry to stable.
      sudo nano /etc/default/rpi-eeprom-update
    8. Check bootloader firmware version
      sudo rpi-eeprom-update

    If bootloader is out of date you will see something like this:

    BCM2711 detected
    Dedicated VL805 EEPROM detected
    *** UPDATE AVAILABLE ***
    BOOTLOADER: update available
    CURRENT: Thu 16 Apr 17:11:26 UTC 2020 (1587057086)
     LATEST: Thu  3 Sep 12:11:43 UTC 2020 (1599135103)
     FW DIR: /lib/firmware/raspberrypi/bootloader/stable
    VL805: update available
    CURRENT: 000137ad
     LATEST: 000138a1
    

    If bootloader is up to date you will see something like this:

    pi@raspberrypi:~ $ sudo rpi-eeprom-update
    BCM2711 detected
    Dedicated VL805 EEPROM detected
    BOOTLOADER: up-to-date
    CURRENT: Thu  3 Sep 12:11:43 UTC 2020 (1599135103)
     LATEST: Thu  3 Sep 12:11:43 UTC 2020 (1599135103)
     FW DIR: /lib/firmware/raspberrypi/bootloader/critical
    VL805: up-to-date
    CURRENT: 000138a1
     LATEST: 000138a1
    
    1. Update bootloader if it is out of date
      sudo rpi-eeprom-update -a
    2. Restart Pi to apply updates
      sudo reboot 
    3. Check to see if update was applied
      sudo rpi-eeprom-update

    2. Select Boot Device Preference

    The default boot setting on our Pi is likely to boot off of SDcard only. We are going to change this so it cycles between trying to boot from SDcard first and then from external USB drive if SD card boot fails.

    Either of the following methods will work.

    Method #1 Use raspi-config utility

    1. run raspi-config utility
      sudo raspi-config
    2. Select option 6 Advanced Options
    3. Select option A6 Boot Order
    4. Select option B1 USB Boot
      You should get pop up window that says “USB device is default boot device”
    5. select ok
    6. select finish and select Yes when asked if you would like to reboot now
      the Pi should reboot like normal. Start SSH session to confirm
    7. shutdown Pi
      sudo shutdown now

    Method #2 Edit Bootloader Configuration

    NEED TO CONFIRM THIS METHOD AGAIN ON NEW PI

    1. open bootloader configuration file
      sudo -E rpi-eeprom-config --edit
    2. Edit the BOOT_ORDER line so that it is like this:
      BOOT_ORDER=0xf41
    3. The entire boot loader file should look similar to this:
    [all]
    BOOT_UART=0
    WAKE_ON_GPIO=1
    POWER_OFF_ON_HALT=0
    DHCP_TIMEOUT=45000
    DHCP_REQ_TIMEOUT=4000
    TFTP_FILE_TIMEOUT=30000
    ENABLE_SELF_UPDATE=1
    DISABLE_HDMI=0
    BOOT_ORDER=0xf41
    

    Installing Ubuntu Server 20.10 on USB 3.0 SSD

    USB booting from Ubuntu Server 20.10 is very simple now with the Pi bootloader.

    1. Connect SSD to PC via SATA->USB cable
    2. Download Ubuntu Server 20.04.1 64bit
      https://ubuntu.com/download/raspberry-pi
    3. Use Raspberry Pi Imager V1.4 or Balena Etcher to write Ubuntu Server 20.10 on the external SSD.
      Be very careful when selecting the drive number that you choose the correct external drive and not your internal computer hardrive!
    4. Connect the SSD to the USB3 port(blue) on the Pi4.
    5. Make sure SDcard used previously to update the bootloader has been remove
    6. Power up the Pi. If everything is good the USB boot should work.
    7. SSH into Pi to confirm boot
      Default user: ubuntu
      default password: ubuntu
    8. upgrade system. Note: The -y parameters disables confirmation dialogs
      sudo apt update && sudo apt full-upgrade -y

    Installing Ubuntu Server 20.04.1 on USB 3.0 SSD

    January 4,2021 NOTE! For some reason this method does not seem to work anymore. Ubuntu will bootup but it stalls. It seems James Chambers has seen this issue well. There seems to be some updated changes to source files that are copied by his script.
    In windows I copied all the boot files(except for check.md5) from previous working image to the new one. This seems to result in the boot working now.

    USB booting from Ubuntu Server 20.04.1 requires additional steps compared to Ubuntu Server 20.10 or latest Raspberry Pi OS. This section is based off of James Chambers instructions. James has some great information on his website so be sure to check out his site.
    In my testing I found that Ubuntu Server 20.10 did not require modifications of the Ubuntu OS to allow for USB boot. See the alternate section for a simpler guide if you are using 20.10.

    1. Connect SSD to PC via SATA->USB cable
    2. Download Ubuntu Server 20.04.1 64bit
      https://ubuntu.com/download/raspberry-pi
    3. Use Raspberry Pi Imager V1.4 or Balena Etcher to write Ubuntu Server 20.04.1 on the external SSD.
      Be very careful when selecting the drive number that you choose the correct external drive and not your internal computer hardrive!
    4. Boot up Raspberry Pi OS via SD card.
    5. SSH into Pi
    6. Connect the SSD to the USB3 port(blue) on the Pi4.
    7. View all the storage devices attached to Pi
      lsblk

    Result should look similar to this:

    pi@raspberrypi:~ $ lsblk
    NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
    sda           8:0    0 111.8G  0 disk
    ├─sda1        8:1    0   256M  0 part
    └─sda2        8:2    0   2.8G  0 part
    mmcblk0     179:0    0  59.6G  0 disk
    ├─mmcblk0p1 179:1    0   256M  0 part /boot
    └─mmcblk0p2 179:2    0  59.4G  0 part /
    

    mmcblk0 is going to be your SDcard. sda is your USB SSD drive.
    The naming of the SSD drive will likely be the same however it could have a different name.
    The MOUNTPOINT column should be blank for the SSD drive. If it is already mounted then you will need to unmount it first.
    8. Mount the drive.

    sudo mkdir /mnt/boot
    sudo mkdir /mnt/writable
    sudo mount /dev/sda1 /mnt/boot
    sudo mount /dev/sda2 /mnt/writable
    
    1. View all the storage devices attached to Pi
      lsblk

    Result should look similar to this:

    pi@raspberrypi:~ $ lsblk
    NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
    sda           8:0    0 111.8G  0 disk
    ├─sda1        8:1    0   256M  0 part /mnt/boot
    └─sda2        8:2    0   2.8G  0 part /mnt/writable
    mmcblk0     179:0    0  59.6G  0 disk
    ├─mmcblk0p1 179:1    0   256M  0 part /boot
    └─mmcblk0p2 179:2    0  59.4G  0 part /
    
    1. Modify Partitions
      This section uses James Chamber’s automated script to modify Ubuntu 20.04.1 so that it can boot.
    2. Execute James’ script
      sudo curl https://raw.githubusercontent.com/TheRemote/Ubuntu-Server-raspi4-unofficial/master/BootFix.sh | sudo bash
      If you get an error saying git is not installed then you can install it using the following and then try running the script again:
      sudo apt install git
    3. If the script ran successfully then you should get something like this:
    pi@raspberrypi:~ $ sudo curl https://raw.githubusercontent.com/TheRemote/Ubuntu-Server-raspi4-unofficial/master/BootFix.sh | sudo bash
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  7983  100  7983    0     0  52/usr/bin/git-:--:-- --:--:-- --:--:--     0
    519      0 --:--:-- --:--:-- --:--:-- 52519
    Found writable partition at /mnt/writable
    Found boot partition at /mnt/boot
    Cloning into 'rpi-firmware'...
    remote: Enumerating objects: 8739, done.
    remote: Counting objects: 100% (8739/8739), done.
    remote: Compressing objects: 100% (4639/4639), done.
    remote: Total 8739 (delta 3646), reused 5116 (delta 3423), pack-reused 0
    Receiving objects: 100% (8739/8739), 98.72 MiB | 1.79 MiB/s, done.
    Resolving deltas: 100% (3646/3646), done.
    Checking out files: 100% (7338/7338), done.
    Decompressing kernel from vmlinuz to vmlinux...
    Kernel decompressed
    Updating config.txt with correct parameters...
    Creating script to automatically decompress kernel...
    Creating apt script to automatically decompress kernel...
    Updating Ubuntu partition was successful!  Shut down your Pi, remove the SD card then reconnect the power.