Raspberry Pi is an awesome little SBC (Single Board Computer), especially the Raspberry Pi 4 that offers a huge improvement over its predecessor. In this blog post I will highlight what you should consider when upgrading your OS to a new hardware (like RPi 3 to RPi 4) or when you consider the same hardware but different (bigger or faster) disk, so SD card migration to a hard drive.
However, this blog post does not offer a complete guide how to proceed with the migration but a set of insights into the process. Most of all, this is a brief history of my experience with Raspberry Pi as a home server.
I started my journey with Raspberry Pi 1 Model B. The very first model which was widely available. Below you can see a picture of it. It still works, however I do not use it any more.
On the other hand, the first model which I used as a 24h server was Raspberry Pi 3 Model B. It was equipped with a Wi-Fi module and I did not have to relay on wired connection any longer. It was a bliss because it was convenient and the performance jump was huge, since now the SBC offered 4 Cortex-A53 cores. It is true that four cores were introduced with RPi 2 but it did not offer wireless connection. So the journey have begun. I started with a simple project which allowed me to do a 24h monitoring station with a pan/tilt camera. You might recall my blog post about it, if not here it is.
To be honest, I have started with a Raspberry Pi 3 Model B and 16GB microSD card. It was around 2017 and then I had installed Raspbian based on Debian 8 Jessie. No long after it came an upgrade to Raspbian based on Debian 9 Stretch. The upgrade was successful at a very first time. Packages were upgraded, my projects with little adjustments were still working.
Time had passed, a year or so, and I started thinking about upgrading my disk space to a new 32GB microSD card with a higher performance class. It would increase both the disk space and the IO performance. However, I wanted to avoid installing a new operating system but migrate the data and services instead. So, I have decided to clone the SD card. However, cloning was a bit of an overshoot since I did not want to clone whole 16GB of memory but only part of it. Back then it was something around 8-10GB of data. I decided to follow a different strategy. I have shrunk the original partition to the size of the occupied memory plus 1GB extra. After testing everything worked fine and I decided to do the cloning. I have used the best tool ever 😉 dd to copy the data from a giver to a donor SD card. Alas! It worked! On target SD card I have expanded the partition and I had 32GB at my disposal.
Time have passed and a new OS upgrade was on the way. It was Raspbian based on Debian 10 Buster. Once again, after testing it turned out that the upgrade should be successful. I did it and it turned out that it was 🙂 It was year 2019, actually the end of that year. Meanwhile, new Raspberry Pi 4 came out on June, 24th 2019. I have considered the upgrade to this model because it now offered up to 4GB RAM. It would be a huge boost. I could have setup other services and do not worry about operational memory. Considering and waiting paid off because on May, 28th 2020 an upgraded RPi 4 came out which supported up to 8GB RAM. Well, if 4GB did not convince me 8GB did it.
Raspberry Pi 4
At the end of year 2020 I decided to get RPi 4 with 8GB of RAM. I have thought about it and I was a bit concerned about one thing. What I wanted to do was to simply switch my microSD card and be done with it. However, due to variety of RPi models the developers decided to enlarge boot partition from 40MB to 256MB. It was required procedure to hold increasing number of images. In addition to this, I had also kept my files in /boot. It was a testing ground for one of my projects. As it turned out switching just SD card to a new RPi4 was done without any issues. That’s great!
No much time have passed when I once again decided to enlarge my disk space. Instead of using 32GB microSD card I have decided to use 256GB. If it is not a huge step I do not know what is. At the same time I had my concerns from hardware upgrade. I wanted to enlarge the /boot partition. However, cloning image was not an option now. I decided to go with a hybrid approach 😀 I thought, why not, I will learn something new and see if this is a valid path. Long story short, I decided to dd the beginning of the SD card, so in other words, I have cloned a part of it. Free space at the beginning, boot partition, and some extra space were copied just to be safe. Next step was to remove /rootfs partition (belonging to OS), enlarge /boot to 2GB in total and then manually create /rootfs partition. I then used my script for backing up to move OS content to a new micro SD card. Well, it worked as a charm!
At that time, I knew that the SD card is just an intermediate step :), really what else 😉 I have waited for native support of USB boot. It was available for RPi 3, however for RPi 4 it was not. Finally, the day have come when that feature was available. I waited couple of months and did some performance tests. USB SSD drive was a huge boost in comparison to SD card. I decided to give it a try. However, now the migration between SD card and SSD USB drive was a bit tricker. There were a few adjustments:
- The mounted device is different now.
- PARTUUID has to be created for USB SSD drive.
- /boot/cmdline.txt has to be adjusted.
- /etc/fstab has to be altered accordingly.
I decided to create a brand new partition table using cfdisk. During this process a new PARTUUID was assigned to each partition of the new drive. First, let me explain what is UUID and what is PARTUUID, and what is the difference between these two.
UUID is Universally Unique IDentifier. So, it is an identifier of a partition which in turn is unique. You have close to no chance to find two partitions with the same UUID. Also, it is universal meaning that it is recognized by different parties. In other words, UUID allows you to assign an unique number to a partition through which you can identify it. For example, if you want to mount a partition you would go with following command
mount /dev/sda1 /mnt/tmp
This will mount partition 1 of device /dev/sda in /mnt/tmp. However, you can mount the same partition using UUID. To find UUID it is advised to use blkid. Then you will get output similar to this
/dev/sda1: UUID="00000000-1111-2222-3333-444444444444" PARTUUID="12345678-01" BLOCK_SIZE="512" TYPE="vfat" /dev/sda2: UUID="00000000-1111-2222-3333-444444444445" PARTUUID="12345678-02" BLOCK_SIZE="512" TYPE="vfat"
Now, to mount the partition using the UUID following would be required
mount UUID="00000000-1111-2222-3333-444444444445" /mnt/tmp
Now, the OS is responsible for founding out what is the proper device name. It is done by resolving the UUID to the device path. This way, if the enumeration of devices change then it is not required to keep record of it. Instead, using UUID is much better option and it can be used on different OS. The best example would be a portable HDD drive connected via USB.
PARTUUID is similar to the UUID, it is unique but in the scope of a device. As it could be seen above. The following partitions have a defined prefix which is common for all the partitions. However the postfix is just an enumeration.
UUID vs PARTUUID
Now, it seems like a right question, why we should use both? The answer is about the support. For command line which is provided during the kernel boot via /boot/cmdline.txt we should use PARTUUID since UUID is not supported at booting time.
First step in migrating to USB SSD drive is to use PARTUUID in the above text file. Most often it looks similar to this
console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
As it can be seen above, the part root=/dev/mmcblk0p2 is pointing to rootfs partition on the micro SD card. Since Raspberry Pi is using microSD cards to boot from then fixing it to the device itself is a good practise. This, however, can be changed. The part with the device has to be exchanged to resemble something like the line below
console=serial0,115200 console=tty1 root=PARTUUID=12345678-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
The above will allow booting process to take place from rootfs partition which in turn was identified by its PARTUUID. Now, the next (and the last) step is to modify /etc/fstab file.
The only one modification has to be done is in reference to fstab file. There, instead of using a device name, similar to the one in the original /boot/cmdline.txt, it is best to use UUID to mount root partition. For example
UUID=00000000-1111-2222-3333-444444444445 / ext4 defaults,noatime 0 1
Please mind the part with UUID=00000000-1111-2222-3333-444444444445. It can be substituted with the PARTUUID and the path to the device itself.
Troubleshooting — a missing SD card
One thing which I have noticed after migrating to SSD drive was a curious entry in kernel log. Every time the Raspberry Pi would boot I have seen something similar to this
[ 1.489639] mmc1: Controller never released inhibit bit(s).
Moreover, this line was marked red so it indicated that there is some error of some kind and I wished to solve it. I have searched for the solution of this issue. However, I did not succeed at first. The issue I was searching for was related to something completely different. One additional symptom which could be seen was a specific blink pattern. The green LED was flashing with ca. 1Hz frequency. Although, when the LED was turned on it was flashing rapidly 4 or 5 times. I have looked at LED blink patterns at Raspberry Pi documentation but unfortunately there was no description for this one. Back to the dmesg… As the message suggests it was related to mmc controller, so the thing which is responsible for transferring data back and forth between SD card and the system. I have even stumbled upon a solution where someone suggested to install different display manager to solve this issue. At the end, the solution was quite trivial. What was required was to insert a micro SD card into the slot. After this the error stopped showing up. What is more, the LED blink pattern ceased the moment the SD card was inserted into the slot. Most likely it was related to the fact that the controller could not start communication with the memory card since it was nowhere to be found.
Let me know it the comments what is your history with Raspberry Pi or any similar SBC.