Skip to content

Instantly share code, notes, and snippets.

@avoidik
Last active December 3, 2025 18:16
Show Gist options
  • Select an option

  • Save avoidik/d8fc39a372db680090edd5322d60848f to your computer and use it in GitHub Desktop.

Select an option

Save avoidik/d8fc39a372db680090edd5322d60848f to your computer and use it in GitHub Desktop.
Migrate Raspberry Pi from SD to USB

Raspberry Pi from SD to USB

How to switch over from SD-card to USB-attached device (USB thumbstick, USB enclosed SSD or HDD, etc.) to have more durable storage option.

Steps

  1. Connect USB device to your RPI

  2. Make sure USB device visible by the system

    sudo fdisk -l
    sudo lsblk

    Usually mmcblk0 is your SD-card, and sda, sdb, sdX are attached USB devices, in my case it was sda. Make sure there is no sensitive data stored on the target USB device. If it's new USB device there should be no partitions reported by fdisk for it. You may want to clean target device using sudo sfdisk --delete /dev/sda (be very careful, it will delete everything on your target device)

  3. Install rpi-clone

    git clone https://github.com/billw2/rpi-clone.git 
    cd rpi-clone
    sudo cp rpi-clone rpi-clone-setup /usr/local/sbin
    sudo rpi-clone-setup -t $(hostname -s)
    sudo rpi-clone -s
  4. Clone SD-card to USB device

    sudo rpi-clone sda # replace sda here with your device name

    This may take some time depending on how much data you have, storage performance, running applications, clients connected, etc. During the process few questions will be asked, read carefully and answer. On the last step where it's asked to examine mounted clone run another connection to RPI, keep existing intact.

    If you've accidentally skipped it just remount it manually:

    • sudo mount /dev/sda6 /mnt/clone/boot.
    • sudo mount /dev/sda7 /mnt/clone
  5. Identify partitions

    Target device will have the same partitions layout as in source device. We need to find out boot and last partition ids.

    sudo lsblk -o name,mountpoint,size,partuuid /dev/sda6 # clone of mmcblk0p6 mounted as /boot
    sudo lsblk -o name,mountpoint,size,partuuid /dev/sda7 # clone of mmcblk0p7 mounted as / or root

    Write down PARTUUID column, in my case these were 3b4344a4-06 for boot and 3b4344a4-07 for root partition respectively

  6. Change cmdline.txt

    To be able to boot from the target device we have to change cmdline.txt file:

    • change root=/dev/mmcblk0p7 to root=PARTUUID=3b4344a4-07 which is the root partition id
    • append at the end of the line rootdelay=5 option to wait while attached device is initialized at boot time

    Complete example:

    console=serial0,115200 console=tty1 root=PARTUUID=3b4344a4-07 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait rootdelay=5
    

    If you'll try to boot without this change you'll get endless Waiting for root message.

    Note: there is one interesting caveat, if you'd like to use LABEL or UUID instead of PARTUUID you must create initramfs/initrd file, hence additional step will be required. Do not use PARTUUID with initrd.

    If you're going to use PARTUUID then you don't need this step (I repeat, skip it and follow the next step).

    • make sure root= set to something like root=LABEL=USB-ROOT
    • cd /mnt/clone/boot/
    • generate initrd file with mkinitramfs -o initrd.sda
    • append initramfs initrd.sda followkernel after rootdelay=5

    Complete example:

    console=serial0,115200 console=tty1 root=LABEL=USB-ROOT rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait rootdelay=5 initramfs initrd.sda followkernel
    
  7. Change fstab

    After the boot process has been completed we would need to mount correct partitions.

    Open /mnt/clone/etc/fstab and do the following:

    • change device /dev/mmcblk0p6 to PARTUUID=3b4344a4-06 (remember to use your own id)
    • change device /dev/mmcblk0p7 to PARTUUID=3b4344a4-07 (remember to use your own id)

    Complete example:

    proc            /proc           proc    defaults          0       0
    PARTUUID=3b4344a4-06  /boot           vfat    defaults          0       2
    PARTUUID=3b4344a4-07  /               ext4    defaults,noatime  0       1
    
  8. Unmount

    Now return back to the initial terminal where we've left rpi-clone process open and hit enter to unmount all partitions. Make sure you don't have the second terminal open somewhere at the mounted paths.

  9. Test

    Shutdown RPI with sudo shutdown -h now, disconnect PSU, unplug SD card, plug PSU in, verify

@jorycz
Copy link

jorycz commented Feb 9, 2024

Just finished this on Raspberry Pi4 without issue on first try. Thanks. /boot/firmware/ was not mounted so before you start, mount it with
mount /dev/mmcblk0p1 /boot/firmware/

@DevinTDHa
Copy link

DevinTDHa commented Dec 9, 2024

For anyone using this guide to try to boot their Raspberry Pi 3b+ from an external drive:

Firstly, I used a more recent maintained version here: https://github.com/geerlingguy/rpi-clone

Then I tried to follow this guide, but the pi would not boot just from the attached external drive. My solution was to leave the SD card plugged in but copy /boot/cmdline.txt and /etc/fstab from the cloned partitions to the SD card. I suppose as long as /boot is ok it will boot from the external drive.

For example:

# Just in case
sudo cp /boot/cmdline.txt /boot/bak_cmdline.txt
sudo cp /etc/fstab /etc/bak_fstab

# Copy the files from sda to sd card
sudo cp /mnt/clone/boot/cmdline.txt /boot/cmdline.txt
sudo cp /mnt/clone/etc/fstab /etc/fstab

# After Reboot
sudo lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0 931.5G  0 disk
├─sda1        8:1    0   256M  0 part /boot
└─sda2        8:2    0 931.3G  0 part /
mmcblk0     179:0    0  59.5G  0 disk
├─mmcblk0p1 179:1    0   256M  0 part
└─mmcblk0p2 179:2    0  59.2G  0 part

The idea is, that the pi will still initially boot from the SD card, but after the kernel is loaded, mount all the files from the external drive. I read this in the forum post Running Raspbian from USB Devices : Made Easy

The easiest and most reliable way to run Raspberry Pi OS on a USB device with any Raspberry Pi prior to the model 4 or 5 is to leave an SD card containing Raspberry Pi OS in place, but use it only for starting the Raspberry Pi OS that is residing on a USB device.

Works for me so far, as I did this because of the SD card going bad.

@solderdot72
Copy link

This does not work too well for me.
I've got a Raspi5 operating on a 128 GB µSD-card and want to clone that onto a 256 GB SSD in a USB case to one of the two blue USB3 ports of the RPi5. The SSD is detected and seen aas /dev/sde.
rpi-clone always stops early with an error message:

:~ $ sudo rpi-clone sde

Booted disk: mmcblk0 127.9GB               Destination disk: sde 256.1GB
---------------------------------------------------------------------------
Part               Size    FS     Label           Part   Size    FS     Label
1 /boot/firmware   512.0M  fat32  --              1      512.0M  fat32  --
2 root             118.6G  ext4   rootfs          2      238.0G  --     --
---------------------------------------------------------------------------
== Initialize: IMAGE partition table - FS types conflict ==
1 /boot/firmware      (64.5M used)   : MKFS  SYNC to sde1
2 root                (106.3G used)  : RESIZE  MKFS  SYNC to sde2
---------------------------------------------------------------------------
Run setup script       : no.
Verbose mode           : no.
-----------------------:
** WARNING **          : All destination disk sde data will be overwritten!
-----------------------:

Initialize and clone to the destination disk sde?  (yes/no): yes
Optional destination ext type file system label (16 chars max): 256 GB SSD

Initializing
  Imaging past partition 1 start.
  => dd if=/dev/mmcblk0 of=/dev/sde bs=1M count=8 ...
  Resizing destination disk last partition ...
    Resize success.
  Changing destination Disk ID ...
  => mkfs -t vfat -F 32  /dev/sde1 ...
  => mkfs -t ext4 -L 256 GB SSD /dev/sde2 ...

Syncing file systems (can take a long time)
Syncing mounted partitions:
  Mounting /dev/sde2 on /mnt/clone
mount: /mnt/clone: wrong fs type, bad option, bad superblock on /dev/sde2, missing codepage or helper program, or other error.
       dmesg(1) may have more information after failed mount system call.
mount: (hint) your fstab has been modified, but systemd still uses
       the old version; use 'systemctl daemon-reload' to reload.
    Mount failure of /dev/sde2 on /mnt/clone.
Aborting!
:~ $

Any idea what might be causing this or how to overcome that issue?

@solderdot72
Copy link

OK... root cause appears to be the label. Neither 256 GB SSD nor "256 GB SSD" is OK. 256_GB_SSD appears to do the trick.

@solderdot72
Copy link

So... rpi-clone appears to work now. The version found here https://github.com/geerlingguy/rpi-clone appears to be the preferred falvor since it is still maintained. The changes in the commandline.txt´ and in the ´fstab are already applied at the end of the process, no need to manually re-work that information. Fine!
However, the Raspi5 does not boot from the thus created SSD in USB case. I have no idea what might be missing. I set the boot order according to https://community.volumio.com/t/guide-prepare-raspberry-pi-for-boot-from-usb-nvme/65700. But to me it looks like it is never attempted to read from the USB SSD case. I conclude that because the case is equipped with a tiny blue LED which flashes if it is read or written. The LED lights up but never flashes. So apparently it is powered but nothing beyond.
Any suggestions on what I might try in this situation?

@avoidik
Copy link
Author

avoidik commented Aug 25, 2025

@solderdot72 have you tried with partitions UUIDs instead of labels? have you tried to increase rootdelay?

@solderdot72
Copy link

@solderdot72 have you tried with partitions UUIDs instead of labels? have you tried to increase rootdelay?

Hi Avoidik,
Thanks for your suggestion. I never tried. Yesterday I succeeded by using a magic USB case. Apparently the one I did use initially lacked whatever magic is required by the Raspi.
With the new one it worked instantly - again using the flavour of rpi-clone that is still maintained, w/o any manual changes applied after the copying process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment