I am using my Raspberry Pi for a backup and torrent server, however even high quality SD cards do not survive for more than a month. Maybe I should have moved the swap file first before attempting what is described here, but in any case, a hard drive is a more reliable medium than an SD card.
So I decided to move the OS to one of the attached hard drives.
In the case of a single usb storage attached to the Pi this would require two steps:
Step 1: The boot loader
You will have to keep the bootloader on the SD card as this is the only device that the Pi recognises and checks early in the boot.
Just prepare an SD card as usual. Then open the boot partition and modify the
cmdline.txt
file in order to boot Linux from the hard drive instead of from the
second SD card partition. The bootloader used here is sufficiently smart to
enumerate the USB devices, so you just need to point to the appropriate USB
device by changing the root
parameter to root=/dev/sdaN
where N
is the
appropriate partition number.
Step 2: Place a Pi distribution on the hard drive
You can just use your SD card and type on your laptop dd if=/dev/mmcblk0p2 of=/dev/sdLN
where L
is the letter for the appropriate external hard drive and N
the
appropriate partition. After that just use gparted
or parted
to expand the
partition. And you are done.
You have to use dd
and not cp
, otherwise your system will boot but it
would be unusable because all the user permissions will be lost.
If you wish you can skip the SD card and dd
directly from the image file.
The issue is that the image file contains two partitions so you will have to
specify and offset in order to copy only the second partition (the Linux
partition, not the bootloader partition). Use parted
to find the appropriate offset:
root@debian-laptop:/home/stefan# parted 2013-12-20-wheezy-raspbian.img
GNU Parted 2.3
Using /home/stefan/2013-12-20-wheezy-raspbian.img
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit
Unit? [compact]? B
(parted) print
Model (file)
Disk /home/stefan/2013-12-20-wheezy-raspbian.img: 2962227200B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 4194304B 62914559B 58720256B primary fat16 lba
2 62914560B 2962227199B 2899312640B primary ext4
(parted) quit
And then use dd
to copy from the offset on (and keep the appropriate size):
root@debian-laptop:/home/stefan# dcfldd if=2013-12-20-wheezy-raspbian.img of=/dev/sdLN skip=62914560 count=2899312640 bs=1
2899312640 blocks (2765Mb) written.
2899312640+0 records in
2899312640+0 records out
If you do not care about the few megabytes dedicated to the boot partition you can just dd the whole image instead of cutting out only the second partition. However this will impose the use of the old-style MBR partition table and as you will see in the next section, this might be undesirable.
Step 3: Make it work with more than one USBs attached
I have more than one hard drive attached, so I need a way to distinguish them. The bootloader enumerates the drives asynchronously so the same drive will have different letter designation each time.
The solution is to address the drives by GUID (a unique identification number). However this is not supported by the old style MBR partition table that is set up by default with most partition and formating utilities. You will need to set up your hard drive to use the GUID partition table (GPT) in gparted first.
After that you repeat step 2 and copy the Linux partition to your hard drive. You have to copy only the Linux partition, because copying the whole image will overwrite the GPT table and reinstate the MBR table.
After you are done with that you need to find the GUID of your Linux partition.
You can do this with gdisk
:
root@raspberrypi:/home/pi# gdisk /dev/sda
GPT fdisk (gdisk) version 0.8.5
Partition table scan:
MBR: hybrid
BSD: not present
APM: not present
GPT: present
Found valid GPT with hybrid MBR; using GPT.
Command (? for help): i
Partition number (1-3): 2
Partition GUID code: 0FC63DAF-8483-4772-8E79-3D69D8477DE4 (Linux filesystem)
Partition unique GUID: 176ADF0D-357D-4C4B-ADC0-371342F444AB
First sector: 2099200 (at 1.0 GiB)
Last sector: 23070719 (at 11.0 GiB)
Partition size: 20971520 sectors (10.0 GiB)
Attribute flags: 0000000000000000
Partition name: ''
Command (? for help): q
And you use this in cmdline.txt
as:
root=PARTUUID=176ADF0D-357D-4C4B-ADC0-371342F444AB
Keep in mind that the GUID is not the same number as the UUID that you would
use in fstab
in order to assign the same mount
points for your drives. This
is a separate (and quite useful, so do it) setup process.
Sources
- Mounting a hard disk image including partitions using Linux
- Mounting root partition by UUID (no initrd needed)
And now the bootloader will always know which hard drive to use in order to boot Linux.