Raspberry Pi 5: Replace microSD with NVMe SSD and migrate system cleanly

I have moved my Raspberry Pi system from a microSD card to an NVMe SSD. Specifically, a 512 GB NVMe is now being used via a PCIe HAT. The aim was to make the system more robust, faster and more stable in the long term.

microSD cards are sufficient for many Raspberry Pi projects, but quickly reach their limits when used continuously with many write accesses. In my case, I run indi-allsky, image storage, database access and regular uploads, among other things. An NVMe SSD is simply the better choice for this: higher performance, significantly longer service life and less risk of file system problems.

In the following, I describe step by step how I migrated the existing system from the microSD to the NVMe during operation.

Requirements

A Raspberry Pi 5 with NVMe HAT
An NVMe SSD with sufficient capacity (in my case 512 GB)
Current Raspberry Pi OS
SSH access or local shell

Check whether the NVMe is recognized

First I checked whether the NVMe is correctly recognized by the system.

 lsblk

The NVMe should appear as a device like nvme0n1. If this is the case, the HAT, SSD and EEPROM are basically OK.

Partitioning and formatting NVMe

The SSD was new and empty. Therefore, I first initialized it with GPT and created a single ext4 partition.

 sudo parted --script /dev/nvme0n1 mklabel gpt sudo parted --script /dev/nvme0n1 mkpart primary ext4 0% 100% sudo mkfs.ext4 /dev/nvme0n1p1

Then I mounted the NVMe.

 sudo mkdir -p /mnt/ssd sudo mount /dev/nvme0n1p1 /mnt/ssd

Copy system from microSD to NVMe

The actual move was done with rsync. The system continued to run, I stopped relevant services in the meantime to minimize write access.

 sudo rsync -axHAWX --numeric-ids --info=progress2 \ --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} \ / /mnt/ssd

The excludes are important because they exclude virtual file systems and runtime data that must not or should not be copied.

After the first run, I made a second rsync pass to synchronize the last changes cleanly.

 sudo rsync -axHAWX --numeric-ids \ --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} \ / /mnt/ssd

Switch root file system to NVMe

In order for the system to boot from NVMe in future, the root partition had to be adapted.

First I determined the PARTUUID of the NVMe.

 sudo blkid /dev/nvme0n1p1

Then I edited the cmdline.txt on the NVMe.

 sudo nano /boot/firmware/cmdline.txt

There I changed the root parameter to the PARTUUID of the NVMe. Important: everything remains in a single line.

Check boot order

To ensure that the Raspberry Pi supports NVMe boot, I checked the boot order.

 sudo raspi-config

Under Advanced Options, I selected NVMe or USB as the boot option. Alternatively, this can be set directly in the EEPROM.

Test and first start of NVMe

Finally, I shut down the system cleanly, restarted it and checked where the root file system is mounted from.

 lsblk

If the root partition is on nvme0n1p1, the move has been completed successfully.
Last step: Enable trim!

 sudo systemctl enable fstrim.timer
sudo systemctl start fstrim.timer

Enjoyed this post?

You can support allsky-rodgau.de with a small coffee on BuyMeACoffee.

Buy me a coffee!