Switch Root Partition to SSD On Raspberry Pi
Raspberry Pi (RPi) is a truly amazing and fascinating device, considering how much power you can get from this tiny device and its amazing versatility. The default and easiest way to set up an RPi is using an SD card, that you can provision using the official Raspberry Pi Imager
Unfortunately, SD cards are fairly slow in both read and write speed, especially compared to even inexpensive solid-state drives (SSDs). A typical SD card has the read/write spead of abouy 30Mb/sec, whereas SSD drives can easily do over 300MB/sec. SD cards are also lessi reliable than their SSD alternatives and generally not recommended for intensive write scenarios.
Raspberry Pi uses two main partitions: boot partition and root partition. As the names would suggest the former is used to load the operating system, where most runtime data is under the root partition. In this blog post we explain how to keep boot partition on the SD card, while moving the root partition to an SSD. In our opinion it gives you the best of both worlds, without any significant headache.
Please note that in such setup you only need a tiny SD Card of handful GBs in size, since most work will be switched to SSD, soon after the setup. 32GB was the smallest quality mini SD card we could find, and what we used, but if you have something even smaller, it will work just fine. 32GB was the smallest quality mini SD card we could find, and what we used, but if you have something even smaller, it will work just fine.
I also like using Ubuntu Servers everywhere (just a personal preference), so that’s what we use in all examples below. You may need to update some commands if you end-up using another Linux distribution.
TL;DR Synopsis
Basic idea is to install everything on SD card, then partition and format a blank SSD disk with ext4 filesystem. After which we duplicate SD Card’s root partition to the SSD, change the label of SSD’s disk to “usbssd” and tell RPi, in cmdline.txt config file, to use the disk with “usbssd” as its root partition, instead of the default, which is partition labeled “writable” on the SD card.
Detailed instructions
First, let’s make sure you know the device name for both your SD card and SSD drive.
To see all attached devices, run: sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
command in your terminal.
> sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
UUID NAME FSTYPE SIZE MOUNTPOINT LABEL MODEL
loop0 squashfs 59M /snap/core20/1627
loop1 squashfs 57.9M /snap/core20/1614
loop2 squashfs 40.6M /snap/snapd/16299
loop3 squashfs 61M /snap/lxd/22761
loop4 squashfs 41.5M /snap/snapd/17032
a7c221ca-e02d-4446-8229-6c6cbd888234 sda 232.9G
mmcblk0 119.1G
5D5B-8026 ├─mmcblk0p1 vfat 256M /boot/firmware system-boot
a7c221ca-e02d-4446-8229-6c6cbd888234 └─mmcblk0p2 ext4 118.8G writable
In my case, the SSD is named sda
and the SD card is named mmcblk0
with mcblk0p1
being the
boot partition and mmcblk0p2
the root partition, respectively.
Now let’s partition and format our blank disk.
Partitioning And Formatting The Disk
To partition the disk, which in my case was blank, we need to use the fdisk
utility:
> sudo fdisk /dev/sda
Since mine was blank, I first created a new partition with the n
command, then accepted all of the
default settings, and finally saved the partition from memory to disk with the w
comamnd, after which
I exited fdisk with the q
command:
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-488397167, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-488397167, default 488397167):
Created a new partition 1 of type 'Linux' and of size 232.9 GiB.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
In your case, your disk pay already have partitions, so make sure to adapt accordingly.
Once we have a single partition on the SSD, it’s time to format it:
> sudo mkfs.ext4 /dev/sda
mke2fs 1.45.5 (07-Jan-2020)
Found a dos partition table in /dev/sda
Proceed anyway? (y,N) y
Creating filesystem with 61049646 4k blocks and 15269888 inodes
Filesystem UUID: 73c7a0dd-91df-4397-8293-64b94f1f0ca0
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
After the formatting successfuly completes, you may want to double-check the result with lsblk
command:
sudo lsblk -o UUID,NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL,MODEL
Duplicating SD’s Root to SSD’s
Since Ubuntu was installed on the SD card, we need to copy all of the data on SD’s root partition, over to
the SSD, before we make a swap. You can do it with a command dd
using a syntax similar to:
> sudo dd if=/dev/mmcblk0p2 of=/dev/sda bs=1M status=progress
420478976 bytes (420 MB, 401 MiB) copied, 9 s, 46.6 MB/s
Please note that we are indicating the root partition of the SD card, after the “if” parameter, as the source and the single partition on the SSD as the destination.
This dd command will take a while, since it copies entire root partition of the SD card to SSD. This (in addition to lower cost) is another reason why you shouln’t buy a larg mini SD card, smaller it is quickly this step will complete.
Alternatively, you can use rsync for the same purpose, which under some conditions may be faster. RSync way of achieving what you need, would look like the following:
> sudo mkdir /mnt/ssd
> sudo mount /dev/sda /mnt/ssd
> export src_dir="/"
> export dst_dir="/mnt/ssd"
> sudo rsync --force -rltWDEHXAgoptx --delete \
--exclude '.gvfs' \
--exclude '/dev/*' \
--exclude '/mnt/clone/*' \
--exclude '/proc/*' \
--exclude '/run/*' \
--exclude '/sys/*' \
--exclude '/tmp/*' \
--exclude 'lost\+found/*' \
$src_dir \
$dst_dir
Once dd
or rsync
is done, we need to fix the label of the partition on the SD drive, since the dd
comand would have set
it to writable
to mimic the SD car and rsync doesn’t set it at all. We do labeling with the following command:
> sudo e2label /dev/sda "usbssd"
The Swap Of partitions
Last, but most importantly, we need to edit /boot/firmware/cmdline.txt configuration file and replace
root=LABEL=writable
with root=LABEL=usbssd
. Once it’s done, you need to restart your RPi, and after
a restart, everything should work with the root partition now being an SSD.