I own a Raspberry Pi 3 model B+ and I came across a problem that I didn’t see that often: I wanted to move the rootfs partition (that is to say, the location on which the root filesystem is physically located) from the SD card, to a USB flash drive.
NB: In this tutorial, I do not change the boot mode of the Raspberry Pi, meaning that it will still boot from the SD card, but it will mount the linux filesystem on the USB drive.
A Raspberry Pi traditionally boots from a SD card, and has two partitions on this card: the boot
partition (quite small) and the rootfs
partition (that takes up the remaining storage space of the SD card). I wanted to move this rootfs partition to the USB drive, to make use of its bigger storage space.
In my case, when I bought and set up my RPi, I just used an old 2GB SD card, and I thought it would be enough to support a light operating system like Raspbian. Unfortunately, I quickly realised that to store additional binaries and install some more libraries (thus, creating files in
/opt
, in/etc
and some additional log files in/var/log
), my 2 Gigabytes were not enough…
You can plug a USB drive, or an external drive to increase your storage space (for instance, for storing pictures, or movies), but this will never replace having a bigger rootfs partition, i.e more space for the OS to use. As I only found very few references online that showed the steps to do so, I decided to write my own tutorial.
I had this useless 16GB USB drive lying around, and I thought it would be the perfect candidate to replace this old 2GB SD card.
Without further ado, let’s jump straight in! Here are the steps I followed:
1) Turn on your RPi with only the SD Card plugged in
Till now, no big deal. It should boot normally, as you’re used to.
2) Plug your (empty) drive inside the RPi
You can list the disks using the command lsblk
.
It should be recognized as /dev/sda
, and (if you never used it) should only have 1 full partition: /dev/sda1
.
If it’s a USB drive or an external drive that you already used, you can wipe it and format it, but it shouldn’t make a difference as the next step will wipe it and format it anyways!
3) Backup your current filesystem from the SD card to the new drive using dd
dd if=/dev/mmcblk0 of=/dev/sda bs=4M status=progress
This command will copy the whole state and content of your current filesystem from the SD card to your newly plugged drive. It could take some time to complete.
As a sanity check: if you run
lsblk
andsudo blkid
, you should now see that/dev/sda1
and/dev/sda2
on your USB drive perfectly replicate the boot and rootfs partitions/dev/mmcblk0p0
and/dev/mmcblk0p1
from the SD card.
WARNING: There is (or might be) still be a problem: In most cases, dd
exactly replicate the partitions, meaning that they might still have the same PARTUUID…
As its name indicates, this UUID needs to be.. well.. unique! The first reason being that it is this ID that you give to the operating system while booting, in order to decide which disk to use to mount the filesystem on.
4) Change the PARTUUID of /dev/sda
using fdisk
In my case, the PARTUUID for both disks was 9b1c6f5e
. I will change the one from my USB drive to d3adb33f
(because why not) using the advanced options of the cmd line utility fdisk
.
sudo fdisk /dev/sda
x # expert options
i # change the disk identifier
<enter the new partuuid in decimal> (here we enter 3551376191, the decimal value of 0xd3adb33f)
r
w
5) Change the rootfs PARTUUID in /boot/cmdline.txt
This file, in /boot
(the boot partition on the SD card) tells the system to mount the linux root filesystem on the disk with given PARTUUID.
So, in this file, instead of:
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=9b1c6f5e-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
We will write:
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=d3adb33f-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
Just in case you want to revert your initial configuration, you can save the old cmdline file as
cmdline.txt.bak
6) Reboot the RPi
sudo reboot
This will safely reboot the device. It will boot from the SD card (as always), but then, mount the root filesystem onto your new USB drive, as intended. From now on, make sure to leave it plugged at all time on the same USB port.
7) Expand the filesystem partition
Last little problem: Our SD card was 2GB, and
dd
copied it identically, making the new partition on the USB drive.. also 2GB! We want to expand our partition so that it occupies all the (e.g 16GB) of our USB drive
There is an option to do that in raspi-config
: If you go to “Advanced Options > Expand Filesystem”.
However, you should get a warning "/dev/sda is not on a SD card, cannot expand filesystem”
This is because the name of partition for the SD card is hardcoded in the raspi-config
script, and that you’re not supposed to mount your filesystem on something else. However, we can circumvent this limitation by just running a few lines:
cp /usr/bin/raspi-config ~ # Copy the raspi-config script in your home folder
sed -i 's/mmcblk0p/sda/' ~/raspi-config
sed -i 's/mmcblk0/sda/' ~/raspi-config # Substitute mmcblk0 for sda everywhere
sudo ~/raspi-config # Run it, and Profit :)
8) There is no Step 8
Voilà! You now have a bigger amount of space to put all your libraries and binaries on!