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. 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. This post still shows both methods, but note that using /dev/sd* for the filesystem is no longer recommended. Please implement the procedure for "Multiple Drives" further down. to stay compatible.
In more recent releases, root=PARTUUID=xxxx is now used in /boot/cmdline, and root=PARTUUID=xxx in /etc/fstab by default.
This method is not for NOOBS installations!
You can use Jessie, Stretch or Buster other versions may work but are not tested.
Using a USB "stick"
If you're looking for a speed improvement, this procedure will be a disappointment for you 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.
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 resize procedure for my disk did not work.
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! 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
[email protected]:~ $ 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
Also check to see if the OS recognized the device: (you can also use the command dmesg | grep sda)
Code: Select all
[email protected]:~ $ 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
Yes, the USB stick can be referenced as /dev/sda[sda] Attached SCSI removable disk < ===
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.
You need to install some programs that are needed for this procedure.
Run:
Code: Select all
sudo apt-get update && sudo apt-get install rsync gdisk
You should not use fdisk or parted, because that stops you from adding drives reliably in the future.
If you know fdisk/parted, gdisk works the same, but adds unique partition identifiers we need later on.
Invoke
Code: Select all
sudo gdisk
Code: Select all
[email protected]:~ $ sudo gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.10
Partition table scan:
MBR: MBR only
BSD: not present
APM: not present
GPT: not present
***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory. THIS OPERATION IS POTENTIALLY DESTRUCTIVE! Exit by
typing 'q' if you don't want to convert your MBR partitions
to GPT format!
***************************************************************
Warning! Main partition table overlaps the first partition by 2 blocks!
Try reducing the partition table size by 8 entries.
(Use the 's' item on the experts' menu.)
Warning! Secondary partition table overlaps the last partition by
33 blocks!
You will need to delete this partition or resize it in another utility.
Command (? for help):
Enter d to delete 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):
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):
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
Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!
Do you want to proceed? (Y/N): y
OK; writing new GUID partition table (GPT) to /dev/sda.
The operation has completed successfully.
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
[email protected]:~ $ 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
Code: Select all
sudo mke2fs -t ext4 -L my_data /dev/sda2
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
[email protected] ~ $ sudo mount /dev/sda1 /mnt
Code: Select all
[email protected]:~ $ 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 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
[email protected] ~ $ sudo rsync -axv / /mnt
...
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.
Code: Select all
var/tmp/ <== this is the last file
sent 858,620,180 bytes received 556,875 bytes 3,141,415.19 bytes/sec
total size is 856,440,892 speedup is 1.00
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
The contents of this file is one very long command string, and we need to replace the reference to the partition on the SD card (root=/dev/mmcblk0p2) to the new USB drive (/dev/sda1)
Here is a copy of the original file on my SD card:
Code: Select all
[email protected]:~ $ sudo nano /boot/cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet
Here is where we are going to decide what we're going to use. If you only use one extra drive -at this moment- (it does not matter how many partitions are on it), you can safely use:root=/dev/mmcblk0p2
Code: Select all
root=/dev/sda1
NOTE 1
To be on the safe side, there is one more command we should add to that single line. 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. If we add a delay of 5 seconds (rootdelay=5), the USB drive should be ready when it's needed. If not, use an even longer period. When you use a stick or SSD drive this will most likely not be needed.
[update] The more up-to-date method now seems go towards adding
Code: Select all
program_usb_timeout=1
NOTE 2
Depending on the power consumption of your stick or drive, and if you use an RPI that supports it, you can add:
Code: Select all
max_usb_current=1
Make sure again the command in /boot/cmdline.txt is still only one line! Save the file and close the editor. Also save this version of the file so we can switch back and forth.
Code: Select all
sudo cp /boot/cmdline.txt /boot/cmdline.usb
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
Code: Select all
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
Code: Select all
/dev/sda1
We are ready to reboot the RPI now. Even when you will need to go to the extended version, try this out first.
Code: Select all
sudo reboot
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.
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
Code: Select all
/dev/sda2 /mnt/my_data ext4 defaults 0 1
Code: Select all
[email protected]:~ $ cat /etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/sda1 / ext4 defaults,noatime 0 1
/dev/sda2 /mnt/my_data ext4 defaults 0 1
#/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
Multiple Drives:
If you will use, or already have more disks that will be directly connected to the USB ports on the RPI, you need to make sure that the kernel always assigns what we now have in /dev/sda1 for the rootfs system. You can never be sure if the drive will be assigned sda or sdb when the system sees multiple drives of whatever kind.
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 (thanks to gdisk). There is a UUID for the drive itself, and a PARTUUID for every partition. Here is where you can see that :
Code: Select all
[email protected]:~ $ sudo blkid
/dev/mmcblk0p1: LABEL="boot" UUID="0F5F-3CD8" TYPE="vfat" PARTUUID="244b8248-01"
/dev/mmcblk0p2: UUID="0aed834e-8c8f-412d-a276-a265dc676112" TYPE="ext4" PARTUUID="244b8248-02"
/dev/sda1: LABEL="rootfs" UUID="ecd95e15-0cdb-46d6-b705-b03b1ad5cb09" TYPE="ext4" PARTLABEL="Linux filesystem" PARTUUID="72d9a26d-1064-4ff0-8e0a-c8ee1102b296"
/dev/mmcblk0: PTUUID="244b8248" PTTYPE="dos"
/dev/sda2: LABEL="my_data" UUID="5cf4fde0-8c39-4b3d-be7a-0236b2e217e0" TYPE="ext4" PARTLABEL="Linux filesystem" PARTUUID="049e6bac-b5d8-4721-9e3e-e8b03f730067"
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 that. Instead of "root=/dev/sda1", we now need to use from blkid:
Code: Select all
root=PARTUUID=72d9a26d-1064-4ff0-8e0a-c8ee1102b296
Code: Select all
sudo nano /boot/cmdline.txt
Code: Select all
root=PARTUUID=72d9a26d-1064-4ff0-8e0a-c8ee1102b296
Code: Select all
sudo cp /boot/cmdline.txt /boot/cmdline.usb
Fstab also needs to know about the actual drive it needs to mount, so we need to give it the UUID of what is currently /dev/sda1.
That information was also in the "sudo blkid" we ran before, so just highlight and paste the UUID code to replace "/dev/mmcblk0p2" or "/dev/sda1" with
Code: Select all
/dev/disk/by-uuid/ecd95e15-0cdb-46d6-b705-b03b1ad5cb09
With this you are again ready to reboot to see the results.
If something goes wrong, you can revert back to the easy method and replace the UUID's one by one to see where the error is. You cannot really break anything so just backtrack your steps and carefully make note of what I did. It should work!
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, similar to what I showed earlier. My /etc/fstab looks like this with both drives added:
Code: Select all
[email protected]:~ $ cat /etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/disk/by-uuid/ecd95e15-0cdb-46d6-b705-b03b1ad5cb09 / ext4 defaults,noatime 0 1
/dev/disk/by-uuid/5cf4fde0-8c39-4b3d-be7a-0236b2e217e0 / ext4 defaults 0 1
# alternatives and backup:
#/dev/sda1 / ext4 defaults,noatime 0 1
#/dev/sda2 /mnt/my_data ext4 defaults 0 1
#/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, no line here
# use dphys-swapfile swap[on|off] for that
If that also works, you can now update and upgrade Debian:
Code: Select all
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get dist-upgrade -y
sudo apt-get autoremove
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