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/ssdThe 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/ssdSwitch 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