Show by Label

Thursday, March 2, 2017

_HowTo: Move the filesystem to a USB drive/stick

This was actually my very first post on the raspberrypi.org forums.
It has been visited a million+ times, so it has been useful to many people.

I was honored when the forum guys selected this post as "sticky", making it easy to find.


Recently, I updated the procedure to more reflect the changes in Raspbian.

Here is the link : https://www.raspberrypi.org/forums/viewtopic.php?f=29&t=44177

Enjoy!

If you like what you see, please support me by buying me a coffee: https://www.buymeacoffee.com/M9ouLVXBdw

To make sure this post does not get lost, I copied it over from the Raspberry Pi Forum,

This procedure will allow you to run Debian from a USB connected drive, instead of the SD card. (latest update: April 2020)

The RPi will still boot from the SD card, but in essence, will no longer write to it. The original idea was to keep the SD card from failing due to excessive writing to it. It will NOT protect you from disk corruption when you pull the power plug without first properly shutting down or halting the RPi. The chances are less likely with this setup, because the corruption happens during write operations to the SD card, but still.

Depending on your setup, this procedure can provide some overall speed improvements, but greatly removes the speed, size and reliability requirements for the SD card.

Starting with the 2017-04-10 kernel version, the Foundation changed to a more reliable way of using drive identifiers.
In more recent releases, PARTUUID=xxxx is now used in /boot/cmdline, and in /etc/fstab by default.
In Buster, there were some more changes, and from then on, you can use

Code: Select all

PARTUUID=xxxx 
. It will be evident when you look at your cmdline and fstab files.


This method is not for NOOBS installations!
This procedure works with Jessie, Stretch and Buster. Newer versions may work but are not tested unless they are added to the list.

Using a USB Flash "stick"
If you're looking for a speed improvement, this procedure will most likely be a disappointment when you are done. The speed advantage, if at all, is at the theoretical very best, only 2x.

Using a "real" disk drive
Things change dramatically however when you use a "real" USB disc or even better, an SSD drive, although the maximum speed is still limited due to the architecture of the RPi hardware. I have just recently tested this procedure an RPi Model 4 using Buster light and that works well too.

If you have an RPi Model 3, you can also try out the latest method of displacing the SD card completely, and really boot from your USB drive. Have a look here, but remember, this is still under development at this very moment and may not work with all drives or in all situations.
https://www.raspberrypi.org/documentati ... des/msd.md It worked for me on a 3B+ and a (rotating) hard disk but there were some issues to go through because the automatic resize procedure for my disk did not work. You need to do this "by hand" but that is not part of this procedure.

If you have an RPi Model 4, you cannot boot directly from another disk (yet) like you can with the Model 3, so this is one way to allow you to run the model 4 from a different and even faster disk, using the USB 3 speeds.

You can also do this for an existing installation It does not need to be a new installation of Debian on your SD card, you can perform this procedure also on an already existing and running system. There is one caveat however, some applications seem to have the access to the SD card "hard-wired", in in those cases it will not work and you have to do this procedure before installing the app. It does not hurt to try though. Just be aware that copying of the data from an already running installation from the SD card to the new drive will take a bit longer due to the data in /var and others.

1. Installation
Power down your RPi or leave it powerless.
Connect your USB stick or drive to the USB slot of the RPI now. Only use one stick or drive for this procedure to avoid mistakes! If you have a real hard disk, it is even more important that you connect that to the USB port before you boot. Older model Pi's cannot handle the power surge when they are running, and will reboot abruptly and can damage the SD card.

After a reboot, check to see if your USB drive is recognized:

Code: Select all

pi@raspberrypi:~ $ lsusb
Bus 001 Device 006: ID 413c:2002 Dell Computer Corp. SK-8125 Keyboard
Bus 001 Device 005: ID 413c:1002 Dell Computer Corp. Keyboard Hub
Bus 001 Device 004: ID 0781:5571 SanDisk Corp. Cruzer Fit
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. LAN9500 Ethernet 10/100 Adapter / SMSC9512/9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Device 004 is the USB stick I'm using. The ID shows a unique manufacturer identifier.
Also check to see if the OS recognized the device: (you can also use the command dmesg | grep sda)

Code: Select all

pi@raspberrypi:~ $ cat /var/log/messages | grep sda
Nov 25 17:56:35 raspberrypi kernel: [    4.024472] sd 0:0:0:0: [sda] 61489152 512-byte logical blocks: (31.5 GB/29.3 GiB)
Nov 25 17:56:35 raspberrypi kernel: [    4.025804] sd 0:0:0:0: [sda] Write Protect is off
Nov 25 17:56:35 raspberrypi kernel: [    4.026652] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
Nov 25 17:56:35 raspberrypi kernel: [    4.063316]  sda: sda1 sda2
Nov 25 17:56:35 raspberrypi kernel: [    4.081595] sd 0:0:0:0: [sda] Attached SCSI removable disk
Jan 13 14:25:51 raspberrypi kernel: [    3.993300] sd 0:0:0:0: [sda] 61489152 512-byte logical blocks: (31.5 GB/29.3 GiB)
Jan 13 14:25:51 raspberrypi kernel: [    3.995088] sd 0:0:0:0: [sda] Write Protect is off
Jan 13 14:25:51 raspberrypi kernel: [    3.996142] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
Jan 13 14:25:51 raspberrypi kernel: [    4.017894]  sda: sda1 sda2
Jan 13 14:25:51 raspberrypi kernel: [    4.022524] sd 0:0:0:0: [sda] Attached SCSI removable disk
Jan 13 14:36:48 raspberrypi kernel: [  691.357635] sd 1:0:0:0: [sda] 61489152 512-byte logical blocks: (31.5 GB/29.3 GiB)
Jan 13 14:36:48 raspberrypi kernel: [  691.358933] sd 1:0:0:0: [sda] Write Protect is off
Jan 13 14:36:48 raspberrypi kernel: [  691.359948] sd 1:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
Jan 13 14:36:48 raspberrypi kernel: [  691.379078]  sda: sda1
Jan 13 14:36:48 raspberrypi kernel: [  691.384786] sd 1:0:0:0: [sda] Attached SCSI removable disk
Jan 13 14:37:05 raspberrypi kernel: [    3.993309] sd 0:0:0:0: [sda] 61489152 512-byte logical blocks: (31.5 GB/29.3 GiB)
Jan 13 14:37:05 raspberrypi kernel: [    3.995048] sd 0:0:0:0: [sda] Write Protect is off
Jan 13 14:37:05 raspberrypi kernel: [    3.996068] sd 0:0:0:0: [sda] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
Jan 13 14:37:05 raspberrypi kernel: [    4.002434]  sda: sda1
Jan 13 14:37:05 raspberrypi kernel: [    4.011623] sd 0:0:0:0: [sda] Attached SCSI removable disk 
[sda] Attached SCSI removable disk < ===
Yes, the USB stick can be referenced as /dev/sda

There is no way of knowing what name the OS assigns to additional USB drives. It could also be /dev/sdb. To prepare for the eventuality of you adding another USB drive or stick, we are going to prepare the RPI for that now.

To prepare the drive to hold a file system, we are going to create one or more partitions, and then format them.

In most cases, the standard fdisk works fine. In some cases, you may have to use parted to get the right UUID information. You can also use gdisk. The instructions are the same.

Invoke

Code: Select all

sudo fdisk /dev/sda
to Creating Partition(s)

Code: Select all

pi@raspberrypi:~ $ sudo fdisk /dev/sda
Welcome to fdisk (util-linux 2.33.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (? for help):
You may get an error message because there could be a partition there already, formatted for Windows that was installed by default. We're going to re-partition and re-format the drive for Linux.
If there is a partition, enter d to delete the partion(s). It will say "Using (partition) 1", that's the default and OK.

Note
I'm now recommending that you pause for a moment, and consider to create two partitions as a minimum. If you have a large USB disk, you may even want more, and now is the time to do it. I will be creating two partitions on my stick. Partition 1 will hold the Raspbian filesystem, and partition 2 will hold my data. I like to keep those two separate as much as I can.

The first partition, for Raspian, can be any size you want (but larger than 2 GB). I'm going to create an 8GB partition, and use the rest for data. The size of the Raspian partition does matter, because the larger it is, the more room the "internal" file system on the card/stick has to move blocks around and optimize the "wear" leveling on these flash drives. If you have a "real" disk, this does not matter.
If you want more partitions, do as I do with the second, just keep track of the size. You may want to put that disk structure on paper first because backtracking is very difficult unless you are an expert.

Create the partitions:
Enter n to create a new partition, and select number 1:
Select the starting sector by hitting Return, then select +8G for the size 0f 8GByte. Now select the default filesystem ('Linux filesystem') by hitting Enter again.

Code: Select all

Command (? for help): d
Using 1

Command (? for help): n
Partition number (1-128, default 1): 1
First sector (34-61489118, default = 64) or {+-}size{KMGTP}:
Last sector (64-61489118, default = 61489118) or {+-}size{KMGTP}: +8G
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help):
OK, now the second partition. I will use one that fills the rest of the disk. If you want more, use the default for the start, and give the size again, and continue until you are done.

Code: Select all

Command (? for help): n
Partition number (2-128, default 2):
First sector (34-61489118, default = 16777280) or {+-}size{KMGTP}:
Last sector (16777280-61489118, default = 61489118) or {+-}size{KMGTP}:
Current type is 'Linux filesystem'
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

Command (? for help):
Now use v for verify to see if everything worked. If you don't like what you see, of if you changed your mind, or made a mistake, no sweat, just hit Ctrl-C and start again. If you are happy, hit w for write to make it permanent. You get one more chance to make up your mind.

Code: Select all

Command (? for help): v

No problems found. 30 free sectors (15.0 KiB) available in 1
segments, the largest of which is 30 (15.0 KiB) in size.

Command (? for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Phew, take a deep breath again, you need the oxygen for the next step.

Formatting the partition(s)

You need to format every partition you created in the previous step. After the partitioning, we now have more devices. device /dev/sda now has two children, called sda1 and sda2 or even more if you were (re)productive.

Code: Select all

pi@raspberrypi:~ $  sudo mke2fs -t ext4 -L rootfs /dev/sda1
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 2097152 4k blocks and 524288 inodes
Filesystem UUID: ecd95e15-0cdb-46d6-b705-b03b1ad5cb09
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
Do the same for the second partition :

Code: Select all

sudo mke2fs -t ext4 -L my_data /dev/sda2
-L is for label, you can call the additional partitions anything you want.

Mounting the root partition

In order to use the new partitions, we need to mount them. Initially we're only going to mount the first partition that will hold the Raspian files (also called rootfs):

Code: Select all

pi@raspberrypi ~ $ sudo mount /dev/sda1 /mnt
Let's see what we've done so far:

Code: Select all

pi@raspberrypi:~ $ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/root       1.2G  885M  244M  79% /
devtmpfs        237M     0  237M   0% /dev
tmpfs           242M     0  242M   0% /dev/shm
tmpfs           242M  4.5M  237M   2% /run
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           242M     0  242M   0% /sys/fs/cgroup
/dev/mmcblk0p1   63M   21M   42M  33% /boot
/dev/sda1       7.8G   18M  7.4G   1% /mnt 
We made the 8GB drive /dev/sda1 available as /mnt for Raspian, so now we can start to use it.

We can copy (mirror) the Debian filesystem data currently on the SD card in /dev/root to the new drive. You can use dd, but that is a bit copy program and, because it also copies the empty space on the SD card, it is very, very slow.
It is better to use rsync that we already installed earlier.
Rsync is a lot faster, but it will still take some time to create a mirror image of the complete file system on the USB drive. We will copy everything from the root "/" to the just mounted drive /mnt (which is /dev/sda1 at the moment)

Code: Select all

pi@raspberrypi ~ $ sudo rsync -axv / /mnt
... 
Because of the -v flag, you can see the files flashing by on the screen, so you can see the progress. You also get an appreciation about the complexity of a complete system.
On my Model B system it took only 5 minutes. Make sure this process does not get interrupted! If there are errors, have a look to see if it is something obvious, or just try the rsync again, or even the whole process. Don't continue unless this worked without errors.

Setting up the new boot procedure

We're now going to tell the system where to find the new filesystem when we are going to boot from the new drive.
The first file we need to change is /boot/cmdline.txt on the SD card.

Before we do that, we're going to create backup copies of that important file so we can easily switch back and forth to booting from the SD card or from the USB disk.

Code: Select all

sudo cp /boot/cmdline.txt /boot/cmdline.sd
This will hold the original boot instructions.
The contents of this file is one very long command string, and we need to replace the reference to the root partition on the SD card to the new USB drive.

Here is a copy of the original file on my SD card:

Code: Select all

pi@raspberrypi:~ $ sudo nano /boot/cmdline.txt
console=serial0,115200 console=tty1 root=PARTUUID=738a4d67-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
 
We are going to change the PARTUUID.

Here's how you do that. I may oversimplify this a bit, but every drive, and in addition, every partition we just created now has a unique identifier. There is a UUID for the drive itself, and a PARTUUID for every partition. Here is where you can see that :

Code: Select all

pi@raspberrypi:~ $ sudo blkid
/dev/mmcblk0p1: LABEL_FATBOOT="boot" LABEL="boot" UUID="4BBD-D3E7" TYPE="vfat" PARTUUID="738a4d67-01"

/dev/mmcblk0p2: LABEL="rootfs" UUID="45e99191-771b-4e12-a526-0779148892cb" TYPE="ext4" PARTUUID="738a4d67-02"

/dev/mmcblk0: PTUUID="738a4d67" PTTYPE="dos"
/dev/sda1: LABEL="rootfs" UUID="ed143dcd-a20d-44ab-a8aa-72d4cce9f2d5" TYPE="ext4" PARTUUID="62576684-01"

(empty lines added for clarity)

For the cmdline.txt file in /boot, we're going to tell the system what partition to boot from, so we need the PARTUUID for the new drive for that. Instead of "root=PARTUUID", we now need to use from blkid: the PARTUUID=62576684-01 from /dev/sda1. First highlight that string with your mouse to copy it. Open the editor

Code: Select all

sudo nano /boot/cmdline.txt
and past that into the open editor instead of the PARTUUID for root (without the "). Make sure that the one line still stays one line, or it may not boot. Save the file. Also save this new /boot/cmdline.txt file so we can switch back and forth later on.

Code: Select all

sudo cp /boot/cmdline.txt /boot/cmdline.usb
Check that you have three versions of this file before you move on. One .txt, the current version, one .sd the original one, and one .usb, the new one.

NOTE 1
To be on the safe side, there is one more command we could add to the configuration. During the power-up/boot sequence, it may take the USB drive a little longer to spin up to speed and be ready, than the OS expects. The default waiting period seems to be 2 seconds for USB devices.
Add

Code: Select all

program_usb_timeout=1
to the end of the /boot/config.txt file.

NOTE 2
Depending on the power consumption of your stick or drive, and if you use an RPI that supports it, you can also add:

Code: Select all

max_usb_current=1
in /boot/config.txt to let the RPI send more juice to the drive.


Mounting the new drive during boot

The next step is to actually mount the rootfs system during the boot process. This is handled by the file system during the later stages of the boot process itself. It uses the information located in the file /etc/fstab.

NOTE We are only going to change the data on the new drive, so we keep the SD card unchanged. This will make it easier to go back and forth with only changing the /boot/cmdline.txt file on the SD card.

Code: Select all

sudo nano /mnt/etc/fstab
It will show something like this:

Code: Select all

proc            /proc           proc    defaults          0       0
PARTUUID=738a4d67-01  /boot           vfat    defaults          0       2
PARTUUID=738a4d67-02            /       ext4    noatime,nodiratime,defaults     0 1

# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that 
We will now change the reference to "/", which is the root filesystem and use the new USB drive instead. Change the PARTUUID for the line with "/" with the PARTUUID of the new drive (62576684-01)
We are ready to reboot the RPI.

Code: Select all

sudo reboot

It helps if you still have a console connected so you can see what is going on during the boot process. And hold your breath again! It will most likely work first time.
When it worked, and you could log in, check the correct root disk by issuing:

Code: Select all

findmnt -n -o SOURCE /
it should report

Code: Select all

/dev/sda1
, which is the new drive.

Note that in some cases, depending on your new drive, the booting process may be a little longer than you are accustomed too.

If something goes wrong however, you need to look at the error messages and back-track carefully. This procedure really works, if you follow it carefully and not make short-cuts or changes. Make it work first, then change whatever you want later.

If it does work, and you have everything running on the USB stick or drive, you can also add the second or more partitions to /etc/fstab.

Adding the second Partition
If you now want to add the second partition on the USB drive, the one I designated for data, do as follows. First create a place holder to mount to.

Code: Select all

sudo mkdir /mnt/my_data
sudo chown pi:pi /mnt/my_data
The last statement will set the ownership rights so you don't need to "sudo" to read/write to this drive. To make it permanently available, you can add one more line to /etc/fstab, like so :

Code: Select all

PARTUUID=xxxx  /mnt/my_data               ext4    defaults  0       1
where xxxx is the PARTUUID from the partition you created.

Reboot, or use "sudo mount -a" and see if you can access that partition too (ls -al /mnt/my_data), it should only have a "lost+found" file.


If that also works, you can now update and upgrade Debian:

Code: Select all

sudo apt-get update
sudo apt-get upgrade 
sudo apt-get dist-upgrade 
sudo apt-get autoremove
And off you go...

Changing the process back to the SD card
If you ever run into problems booting from the USB drive, you can move the original /boot/cmdline.txt back by putting the SD card back into your PC, and use the Filemanager to copy the file /boot/cmdline.sd back to /boot/cmdline.txt. You don't need to do anything to the /etc/fstab file on either the SD card or the USB drive if you are going to boot from the SD card. (watch out: if you want to do this while the card is in your PC, do not use rename, because Windows may rename the file called cmdline.txt to cmdline.txt.txt !)
If your system still works with the USB stick, you can also make the changes to the cmdline files from within Debian (in /boot). You can also run a disk check in the USB drive when you have dismounted that drive and run from the SD card.

Note
One thing you need to keep track off is the difference in kernel versions between the boot code on the SD card and the file system on the USB drive when you apt-get upgrade. The original kernel software on the SD card may get out of synchronization with the newer boot files on the DOS partition. One way to fix that is to revert back to the SD card and also update that file system with apt-get upgrade.


This updated version/revision was made possible by the contributions of many users. Their posts are below, just be aware that many inputs or comments are now outdated, or hopefully integrated. It was the only way for me to keep new users from going through 12 pages (currently) of comments, discussions and other contributions.

Enjoy and stay tuned!
Paul

2 comments:

Owais Khan said...
This comment has been removed by a blog administrator.
Kavin cook said...
This comment has been removed by a blog administrator.