5

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
  • 151
  • 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

3 Answers3

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](https://github.com/billw2/rpi-clone) 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
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
  • 54,718
  • 26
  • 92
  • 182
  • 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
1

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
  • 18,728
  • 2
  • 27
  • 57
  • 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](https://www.raspberrypi.org/documentation/hardware/raspberrypi/bootmodes/msd.md), "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](https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md#raspi-config). 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](https://duckduckgo.com/?t=ffab&q=raspberry+pi+boot+from+USB+drive&atb=v278-2__&ia=web) I see an [article at `Tom's Hardware`](https://www.tomshardware.com/how-to/boot-raspberry-pi-4-usb) 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