Wednesday, September 28, 2016

Raspberry Pi, More About Installing a SSD

I just finished helping a reader get an SSD (solid state drive) running on his Pi, and realized that the documentation that the Pi folk provided <link>, while correct, left some things kinda hanging for people doing this. Mainly, what to expect when you type the various commands, basically what to expect while actually doing it. Don't misunderstand, they didn't mess anything up, or leave something out, they did a great job, but some of us dweebs can get lost in the responses and such that come back.

I saved key parts of hooking up a SSD to a USB port and getting the system over to it, then booting from it, to serve, both as an extended example, and as notes to myself for next time. Yes, I read my own blog to see what the heck I did last time.

So, you get yourself an SSD and some kind of enclosure to hold it. I went to Amazon and grabbed one of the cheapest combinations I could find and used that. I wound up with two of them due to a shipping problem. Actually, this is a cute story, so I'll briefly tell you about it.

I ordered a drive and USB enclosure and then waited for it to come in. It didn't. The Amazon order said it was delivered, but it wasn't on my porch or in the box down the road. Naturally, I called Amazon and complained. They immediately refunded the money and put in an expedited order for new devices. I got the new devices in two days. That was absolutely great; I love Amazon customer service a lot.

A week later, the neighbor came over with the original package. They just moved in and forgot about it until it turned up again. I thanked him then paced around wondering whether I should tell Amazon, or just keep the drive. You guessed it, conscience got to me and I called Amazon. I had a choice, send it back (they pay shipping) or buy it. I bought it; since I actually need three of them, might as well keep this one. Sure, it's more expensive than others I can get, but I already had it in my greedy hands. That's the drive I used in the explanation below. I still want to get a really cheap one and try the entire process again with cheaper hardware, but that can wait for later.

Anyway, you have your new SSD in hand and want to put the Pi software on it and use the thing, so plug it in and partition it. Since this is the first USB drive, it will be recognized and assigned /dev/sda; if you have another drive, unplug it or figure out what the drive shows up as. Then:

pi@housemonitor:~$ sudo parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mktable msdos
(parted) mkpart primary fat32 0% 100M
(parted) mkpart primary ext4 100M 100%
(parted) print
Model: ASMT 2115 (scsi)
Disk /dev/sda: 63.4GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number  Start   End     Size    Type     File system  Flags
 1      1049kB  99.6MB  98.6MB  primary  fat32        lba
 2      99.6MB  63.4GB  63.3GB  primary  ext4         lba
Information: You may need to update /etc/fstab.
The things I typed in are bold so you can see them easily and you have to type control D to get out of parted. Folk that have done this before will wonder why I created a boot partition when I'm not going to use it. Well, I figure the work on alternate boot capabilities will continue and I want a boot partition on there in case I want to use it later. It doesn't take much space, and I have way more than I need, so why not? Occasionally I actually think ahead.

Now we have to put file systems on the new partitions. We do that with mkfs and here's what it looks like:

pi@housemonitor:~$ sudo mkfs.vfat -n BOOT -F 32 /dev/sda1
mkfs.fat 3.0.27 (2014-11-12)
pi@housemonitor:~$ sudo mkfs.ext4 /dev/sda2
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 15442176 4k blocks and 3866624 inodes
Filesystem UUID: f1df7b73-5872-43b8-b0da-29d6d139557d
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This makes the filesystems on both the /BOOT and / partitions. Now you're ready to put something on there. In most cases, you want to take a running system, clone it on the new drive, and then use it without having to change a bunch of stuff. So, let's get them mounted so we can copy what we already have to the new drive.

pi@housemonitor:~$ sudo mkdir /mnt/target
pi@housemonitor:~$ sudo mount /dev/sda2 /mnt/target/
pi@housemonitor:~$ sudo mkdir /mnt/target/boot
pi@housemonitor:~$ sudo mount /dev/sda1 /mnt/target/boot/
This mounts both of the new partitions. Next, you may have to install rsync; it depends on which version of Jessie you started with. Jesssie lite doesn't come with rsync, while the full version does. I had it on one Pi and not on the other. If you need to go get it do an update first to be sure you get the latest.

sudo apt-get update

There will be a ton of output from this depending on how recently you updated. I always get lots of stuff since I rarely update the machines. Then actually install rsync:

sudo apt-get install rsync

This will also have lots of output. You've done this before, you know what you're going to get. Now, copy all the stuff from the SD card to the new drive:

sudo rsync -ax --progress / /boot /mnt/target

Not only will this produce voluminous output, it takes a good long time. If you have a minimal system like Jessie lite, you can wait around for it. If you have the full system with a lot of installed packages, take a break. I fed the dog, put on some laundry, called the telephone company and it still wasn't done.

Since all my Pi's are run headless (without a monitor or keyboard), I had to generate new keys for ssh. The easy way to do this is to mount the new partitions and pretend they are the real thing. If that's unclear, take a look at the documentation for chroot:

pi@housemonitor:~$ cd /mnt/target
pi@housemonitor:/mnt/target$ sudo mount --bind /dev dev
pi@housemonitor:/mnt/target$ sudo mount --bind /sys sys
pi@housemonitor:/mnt/target$ sudo mount --bind /proc proc
pi@housemonitor:/mnt/target$ sudo chroot /mnt/target

Now, actually regenerate the keys. This warns that it will take a while to do this, but compared to the rsync above, it's nothing.

root@housemonitor:/# rm /etc/ssh/ssh_host*
root@housemonitor:/# dpkg-reconfigure openssh-server
Creating SSH2 RSA key; this may take some time ...
2048 1b:51:b1:64:a3:ad:2a:3c:3f:54:b0:7e:e5:e8:b2:76 /etc/ssh/ (RSA)
Creating SSH2 DSA key; this may take some time ...
1024 fc:75:4e:17:77:f1:7e:4c:50:47:95:d7:94:3a:24:31 /etc/ssh/ (DSA)
Creating SSH2 ECDSA key; this may take some time ...
256 3f:56:f8:02:92:fe:c6:a5:3d:3b:b7:58:f1:f1:2a:0b /etc/ssh/ (ECDSA)
Creating SSH2 ED25519 key; this may take some time ...
256 cc:ba:5e:54:df:52:19:1c:ec:be:96:39:ca:55:3b:8a /etc/ssh/ (ED25519)
[ ok ] Restarting OpenBSD Secure Shell server: sshd.
root@housemonitor:/# exit

Whew ! Unmount the new stuff which will make sure it gets written out, and then we'll make changes to the boot files to complete the process.

pi@housemonitor:/mnt/target$ sudo umount dev
pi@housemonitor:/mnt/target$ sudo umount sys
pi@housemonitor:/mnt/target$ sudo umount proc

This next part may confuse you some. I've noticed that all the examples out there don't show the mistakes we all make in following some tutorial or written process. I decided, for one window, to show what actually happened during some of the changes I made; this is where I edited the cmdline.txt and fstab files. I did a cat of the file contents before and after since the editor clears the screen of the changes:

pi@housemonitor:/mnt/target$ cd /boot
pi@housemonitor:/boot$ ls
bcm2708-rpi-b.dtb       COPYING.linux  LICENCE.broadcom
bcm2708-rpi-b-plus.dtb  fixup_cd.dat
bcm2708-rpi-cm.dtb      fixup.dat      overlays
bcm2709-rpi-2-b.dtb     fixup_db.dat   start_cd.elf
bcm2710-rpi-3-b.dtb     fixup_x.dat    start_db.elf
bootcode.bin            issue.txt      start.elf
cmdline.txt             kernel7.img    start_x.elf
config.txt              kernel.img     System Volume Information
pi@housemonitor:/boot$ cp cmdline.txt
cp: cannot create regular file ‘’: Permission denied
pi@housemonitor:/boot$ sudo !!
sudo cp cmdline.txt
pi@housemonitor:/boot$ sudo vi cmdline.txt
pi@housemonitor:/boot$ cp cmdline.txt cmdline.usb
cp: cannot create regular file ‘cmdline.usb’: Permission denied
pi@housemonitor:/boot$ sudo !!
sudo cp cmdline.txt cmdline.usb
pi@housemonitor:/boot$ cd /mnt/target/etc/
pi@housemonitor:/mnt/target/etc$ cat fstab
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
pi@housemonitor:/mnt/target/etc$ sudo vi fstab
pi@housemonitor:/mnt/target/etc$ cat fstab
proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    ro,auto,user,exec,async          0       2
/dev/sda2       /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that
I'm constantly forgetting to use 'sudo' to edit system files. It really gets annoying making the same mistake over and over again. 

Now, the trial by fire. Notice above that I saved the cmdline.txt file for the SD card. That's just in case this doesn't work. If it fails all I have to do is copy the file back in place on a PC (remember, the BOOT partition is msdos) and I'm back to the SD card and can fix whatever I messed up. So, let's unmount the new disk and reboot the Pi:

pi@housemonitor:/mnt/target/etc$ cd
pi@housemonitor:~$ sudo umount /mnt/target/boot
pi@housemonitor:~$ sudo umount /mnt/target
pi@housemonitor:~$ sudo reboot

I usually find myself gritting my teeth at this point, and honestly, the Pi got into one of those situations where it wouldn't connect to the network. I had to walk over and cycle power to get it up. This happens to me once in a while, and the Pi will almost always come up after some period of retrying. I just got tired of watching it blink while it tried to connect. But, it came up and I did a 'df' to show the new disk was mounted and the SD card was read-only.

login as: pi
pi@'s password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Sep 28 09:09:58 2016
pi@housemonitor:~$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/root       60666940 3968532  53593592   7% /
devtmpfs          218416       0    218416   0% /dev
tmpfs             222688       0    222688   0% /dev/shm
tmpfs             222688    5052    217636   3% /run
tmpfs               5120       8      5112   1% /run/lock
tmpfs             222688       0    222688   0% /sys/fs/cgroup
/dev/mmcblk0p1     61384   20400     40984  34% /boot
tmpfs              44540       0     44540   0% /run/user/1000
pi@housemonitor:~$ ps ax|grep python
  455 ?        Sl     0:09 /usr/bin/python /home/pi/src/house/
  458 ?        S      0:01 /usr/bin/python /home/pi/src/house/
  461 ?        Sl     0:05 /usr/bin/python /home/pi/src/house/
  462 ?        Sl     0:03 /usr/bin/python /home/pi/src/house/
  464 ?        Sl     0:05 /usr/bin/python /home/pi/src/house/
  466 ?        S      0:01 /usr/bin/python /home/pi/src/house/
  468 ?        Sl     0:08 /usr/bin/python /home/pi/src/house/
  470 ?        Sl     0:04 /usr/bin/python /home/pi/src/house/ 4
  807 pts/0    S+     0:00 grep python
I also did a 'ps' to check that the processes I usually run started automatically. Everything worked.

So folks, here's a real example of how to do this with a lot of the text that comes along with it. It took me less than a morning, even with the long rsync process. I didn't bother backing up the SD card since I was only changing the one file, cmdline.txt, on it and even that was backed up. The big advantage to me is that the SD card is fully bootable and is very unlikely to fail since it is never written to. I can use it to fix something if I need to at a minutes' notice.

Have fun.


  1. Maybe you have a plan that I'm not aware of, but why not just use a flash drive? If you're funneling a SSD over USB anyways, there's no speed benefit. In fact, it's probably slower.

    I've had the same SD card corruption issues that you've had and did this same (similar) method of booting from SD and running from a USB stick and it works wonders.

    1. Actually, I don't have much of a plan, but I tried the USB dongle idea and it failed horribly. I was able to install it and get it to work and was really happy until the USB dongle crapped out and marked itself READ-ONLY. Turns out that this particular thing isn't all that uncommon, so I won't try that again. I really wanted a small SSD, but the price point for this was reasonable, and I've found other possibilities since.

      The entire episode is described in the two blog posts:

  2. Dave, I admire people share knowledge. Thank you very much for this clear (as usual) article. It seems to me I will try 8^)