6

I have set up my Raspberry Pi 4 for use as a small home server, running OpenMediaVault. Currently, the Pi is running from an SD card, but I'd like to switch to an SSD. I've found several tutorials explaining how to do this, but all of them use the SD Card Copier utility (available with the desktop version of Raspberry Pi OS) to clone the OS from the SD to the SSD. I need to use the Lite version of the OS that does not have a desktop. Is there a way to clone the SD to SSD using the command line, and then boot from the SSD? Can I use dd for this purpose?

I have no way to mount the SSD on my laptop (and would prefer not to buy an adapter just for this purpose), so I need to work from the Pi itself.

Matthijs
  • 169
  • 1
  • 1
  • 3
  • Afterthought: not very happy with my choice of tags, but did no find any that suited the question any better...ssd might be a useful tag to add to the collection? Don't have enough reputation to do that myself. – Matthijs Jun 28 '21 at 09:14
  • 1
    Don't use dd for copying a working system; its fine for copying images, but there are subtle differences between an image and a working system. Use rsync (although I would assume rpi-clone is more automated and hence easier, I can't say because I've never used it): https://raspberrypi.stackexchange.com/a/5492/5538 – goldilocks Jun 28 '21 at 13:47

4 Answers4

3

Have a look at rpi-clone. It's on GitHub. The author is Bill W(ilson?).

ArjenR
  • 101
  • 1
  • 4
  • Thanks, will have a look. I guess this is the application you're referring to? – Matthijs Jun 29 '21 at 08:35
  • Yes it is. On subsequent executions it is usually quick. You can exclude folders of your choice. Certain folders are not copied, since it is not useful to copy them. The part-uuid's are changed on the clone which is a good precaution. – ArjenR Jun 29 '21 at 09:56
  • rpi-clone for all life. I use it and it saves me a couple of times ;) – sineverba Oct 29 '21 at 17:29
2

You shouldn't make a backup of a "live" filesystem with dd - it has its uses, but backing up a "live" system is not one of them. It's been said of one who follows this practice: "If you're lucky, the filesystem corruption will be detected as soon as you try to mount the copy. If you're unlucky, it won't be detected until later."

I'll assume you know how to configure your RPi to boot from an external SSD, & won't cover that. But if you're unsure about this, read USB mass storage boot.

Cloning your existing microSD to a bootable SSD from the command line on a single RPi is a two-step process:

Step 1: Install image-utils & make an image file clone of your SD card. Start at the Show Me How heading of this post, or do something like this (Note: my exe copy of image-backup lives in ~/bin):

$ sudo /home/pi/bin/image-backup

Answer the questions when prompted. Creation of the image file required approx 2.5 minutes to complete on my system.

My image file was saved as:

/mnt/Passport2TB/img_backups/20210701_Pi4B_imagebackup.img
Yours will likely be different, but note its name and location as you'll need this in Step 2.

Step 2: We'll now use dd to copy the image file created in Step 1 to the SSD. This avoids issues with dd mentioned previously because neither the input file (if), nor the output file (of) are mounted/active.

Connect your SSD to one of the USB ports, then use lsblk to examine all block storage devices connected to your system. For example, here's mine:

$ lsblk --fs
NAME        FSTYPE LABEL       UUID                                 FSAVAIL FSUSE% MOUNTPOINT
sda
└─sda1      ext4   PASSPORT2TB 86645948-d127-4991-888c-a466b7722f05    1.5T    11% /mnt/Passport2TB
sdb
mmcblk0
├─mmcblk0p1 vfat               6969-16D1                             206.5M    19% /boot
└─mmcblk0p2 ext4               f6ea6ef9-68be-479d-b447-5f76391cc02f   22.7G    18% /

Note carefully:

  1. sda1 is a mounted USB drive where I saved the image file created in Step 1. Confirm that this partition/device is mounted by reviewing the MOUNTPOINT column in the output.
  2. sdb is the SSD on my system. Your SSD may be assigned a different device designation (sdc, sdf, etc). Confirm that your SSD drive (or sdb in this example) is not mounted by confirming there is nothing listed for it in the MOUNTPOINT column. If it is mounted, un-mount it using sudo umount /dev/sdb & verify this by re-running lsblk --fs.
  3. mmcblk0 is your microSD card - the card you currently boot from. Of course it is mounted at two points: the root ext4 partition /, and the boot FAT partition /boot.

Once you're satisfied with your examination, you are ready to copy the image file created in Step 1 to the SSD:

$ sudo dd bs=4M status=progress if=/mnt/Passport2TB/img_backups/20210701_Pi4B_imagebackup.img of=/dev/sdb conv=fdatasync

sample output :

4383047680 bytes (4.4 GB, 4.1 GiB) copied, 160 s, 27.4 MB/s 1048+1 records in 1048+1 records out 4396003328 bytes (4.4 GB, 4.1 GiB) copied, 165.296 s, 26.6 MB/s

See man dd if you've any questions re the options.

You may now remove your microSD card, and boot from your SSD.


DEPRECATED If you had a 2nd system with a GUI, you might consider using rpi-imager in Step 2 - but think of all the fun? you'd be missing.

Step 2: Install rpi-imager on a desktop/laptop system & use it to "install" the image file you created in Step 1. Installation of rpi-imager on a Linux system using apt (e.g. Debian/Ubuntu) is as follows:

sudo apt-get update  
sudo apt-get full-upgrade   
sudo apt install rpi-imager

note that the update and upgrade steps should always be performed prior to installation of new packages.

Seamus
  • 21,900
  • 3
  • 33
  • 70
  • 1
    "You probably could use dd" - it is not a good idea to clone a running system itself. Does image-utils can safely clone an running system of itself? – Ingo Jun 29 '21 at 08:32
  • Thanks. You assume I know how to boot from SSD, but this is exactly what I am trying to accomplish...From the tutorials I've seen, booting from SSD involves copying the OS from SD to the SSD in some way. I don't have access to a graphical interface, so I cannot ( or don't know how to) use the SD card copier utility. The rpi-imager utility you suggest seems to have a graphical interface as well. Or am I wrong? Can I use it from the command line? – Matthijs Jun 29 '21 at 08:33
  • @Matthijs: First: Yes, you can use rpi-imager from the command line. Second: According to the RPi documentation, "Newer" RPi 4Bs support USB boot by default. This isn't completely clear however, as they do not tell us what "newer" is. Read the document in that link, and then read the 6 steps for raspi-config in this one. After that, if you're still uncertain, let us know in a comment, or by editing your question. – Seamus Jun 29 '21 at 16:03
  • @Matthijs: Another thought: The "official documentation" published by the RPi Organization is usually accurate, but at times unclear. Looking at my search results I see an article at Tom's Hardware that's fairly current & clearer than the "official documentation". It's worth a look. The only adjustment I think we'll need is in Steps 14 & 15 to use the CLI rpi-imager instead of the GUI-fied SD card copier. Your thoughts? – Seamus Jun 29 '21 at 16:25
  • I'm familiar with the article you mention, and similar other articles. My issue is not so much the hardware; I haven't tried yet (lack of time...) but I think I can get the pi to boot from the ssd. My problem is getting the OS software onto the ssd. If rpi-imager works from the command line, that should solve the problem. – Matthijs Jul 01 '21 at 09:00
  • I've installed rpi-imager on the rpi, but cannot get it to work. Can you tell me how to use it from the command line? I always get an error "Could not connect to any X display", so it looks like a GUI – Matthijs Jul 01 '21 at 13:30
  • @Ingo: You are correct. It has finally sunk in that the OP wants to do all of this on his RPi OS Lite system. But yes - image-utils can safely and accurately create an image file while the system is running (it's based on rsync - not dd). I blew this one! – Seamus Jul 01 '21 at 21:28
  • @Matthijs: My apologies! - I seem to have made a very bad assumption: I assumed that rpi-imager could be run from the CLI, and that's apparently incorrect. And so, we will need to use dd in Step 2 (but not in Step 1). I've verified & updated my answer now, and it should work for you also. Again, my apologies for the confusion and bad advice. One other thing you can do now is to remove rpi-imager and the crapload of GUI libraries it installed: sudo apt-get purge rpi-imager. – Seamus Jul 02 '21 at 03:26
1

There is nothing magical about SD Card Copier - is just reads the SD Image, creates the appropriate partitions on the target then uses a file copy similar to rsync to copy contents.

I am sure you could do the same using dd although you would then be responsible for expanding the root partition.

I haven't done this, but do similar from SD Card to SD Card. This needs to be cognisant of PARTUUID which may need adjusting depending on how the partitions are created. Again I have scripts to change PARTUUID which is a good idea for clones (SD Card Copier has an option for this).


NOTE that I wouldn't do this; I would backup to an image and burn to a SSD.

If you have an SSD you will need a USB adapter for the Pi, so you already have the hardware to mount on the laptop. However if you REALLY want to do this on the Pi read on:-

First attach your SSD (probably in /dev/sda) then use dd to copy /dev/mmcblk0 to the SSD.

Then use the following script on the SSD to check PARTUUID.

If this is OK you could then boot to the SSD, and use raspi-config to resize the root partition.

If not you will need to change to match your PARTUUID

#! /bin/bash
# 2020-03-09
# 2021-02-10
# Check consistency of Partition ID on mounted SD Card

BOOT_MOUNT='/mnt/SDA1' ROOT_MOUNT='/mnt/SDA2'

Check/create Mount Points

if [ ! -e $BOOT_MOUNT ]; then mkdir $BOOT_MOUNT fi if [ ! -e $ROOT_MOUNT ]; then mkdir $ROOT_MOUNT fi echo "mounts " $BOOT_MOUNT $ROOT_MOUNT if [ -e /dev/sda ]; then SD1='/dev/sda1' SD2='/dev/sda2' SD='/dev/sda' else SD1='/dev/sdb1' SD2='/dev/sdb2' SD='/dev/sdb' fi echo $SD

Mount Partitions

if ! $(mountpoint -q $BOOT_MOUNT); then sudo mount $SD1 $BOOT_MOUNT # mount partition containing boot files fi if ! $(mountpoint -q $ROOT_MOUNT); then sudo mount $SD2 $ROOT_MOUNT # mount root partition containing OS files fi

Determine Disk identifier of SD Card

DISKID=$(sudo fdisk -l $SD | awk '/Disk identifier/ {print $3};' | sed 's/0x//')

Use sed to delete all BEFORE PARTUUID= and all AFTER -0 in $BOOT_MOUNT/cmdline.txt

ROOTPART=$(sed -e 's/^.PARTUUID=//' -e 's/-0.$'// $BOOT_MOUNT/cmdline.txt)

echo -e "Disk ID\t\t"$DISKID echo -e "root PARTUUID\t"$ROOTPART

find first PARTUUID ext4 in $ROOT_MOUNT/etc/fstab

EXISTFSTABPART=$(awk '/PARTUUID.ext4/ {print $1; exit};' $ROOT_MOUNT/etc/fstab | sed -e 's/^.PARTUUID=//' -e 's/-0.*$'//)

echo -e "Existing fstab\t"$EXISTFSTABPART

if [ $DISKID = $EXISTFSTABPART ]; then echo "Looks OK!" else echo "Partition ID mismatch!" # Edit cmdline.txt & fstab to new DISKID & create new temporary files sed -e "s/$ROOTPART/$DISKID/" $BOOT_MOUNT/cmdline.txt > cmdline.txt.new sed -e "s/$ROOTPART/$DISKID/" $ROOT_MOUNT/etc/fstab > fstab.new echo -n "Set DiskID to ${DISKID} on $SD (y/n)? " while read -r -n 1 -s answer; do if [[ "${answer}" = [yY] ]]; then echo "Change" sudo cp -v cmdline.txt.new $BOOT_MOUNT/cmdline.txt sudo cp -v fstab.new $ROOT_MOUNT/etc/fstab break else echo "Aborted" exit fi done fi

Milliways
  • 59,890
  • 31
  • 101
  • 209
  • 1
    Thanks. Can you explain exactly what steps I would need to take to accomplish this? I'm new to all of this. – Matthijs Jun 29 '21 at 08:38
0

I suggest keeping an extra 3B+ or higher for this. That way you can just the GUI SD Copier. It's just the fastest and most convenient method.

jdrch
  • 1
  • 3