Some time ago I started playing with PiDrive project. I implemented an application that I think will be useful to people using it in the end – some simple IPv6 enabler/browser and DynDNS client. But I kinda cheated and implemented it on the ARM board I already had at home. Over the last week I didn’t had much free time, but I still continued on the project and I got my Pi booting my custom image. How will PiDrive boot was subject to lengthy discussions on mailing list, so I wanted to provide a proof of concept of how do I think it can be done. As it is long post, TLDR version at the end 😉
First, let’s take a look at how Raspberry boots. Most ARM board I encountered so far used u-Boot that was either in internal flash memory or on the SD card at some predefined address. Raspberry searches for a files with predefined names on FAT filesystem that it expects to find on first partition of your SD card. On one hand, it looks weirder, on the other it is simpler if you don’t have any prior experience with ARM. And if you do, you can still put u-Boot there to get all the options u-Boot provides.
Other observation to take into account made by others is that SD cards die quickly in those devices. Mine didn’t yet, but I don’t do any crazy stuff and tend to be lucky. But let’s take for granted that during the life of the device, SD card might die and maybe even multiple times. We should somehow address that. And recovering from broken SD card should be simple so even average Joe can do that.
As I’m openSUSE guy, I obviously picked openSUSE to power my PiDrive, but nothing I did should depend on chosen distribution. I picked 13.2 as Leap for armv7 is not ready yet (about that some other time) and I added few packages that I think can be useful on OBS in separate project.
Last point I have is that I would personally prefer to have system installed on SD card. It will be slower to start, but it will let harddrive to spin down and go to sleep when not used. Prolonging it’s life and reducing the noise of spinning drive. But if system is running from SD card, second paragraph is even more important – we need to gracefully handle SD cards death.
How I boot my Pi
Now you know from what I started and let’s take a look with what I ended up. I wanted to make firsts time installation as easy as possible. As SD cards come preformatted to FAT already, all you have to do to boot is just to copy some files there. I found out what files I need there, tweaked a configuration a little bit and compiled my own kernel. Why? To compile all drivers needed during boot directly in and to include custom initramdisk. For those who don’t know, initramdisk is, as name suggests, small disk in RAM that contains few programs and script that is executed before the system boots and can be used if you need to do some complicated stuff before booting. And that is exactly what I had in mind.
On first boot, my initramdisk takes everything on SD card, copies it to memory (we have 1G of RAM and pretty much nothing is running at this point), then it repartitions the SD card and copies the files back. It makes first partition with FAT smaller and creates new Ext2 partition behind it. What are those for? First partition contains stuff needed by the board to boot up (various firmwares and kernel) but also squashfs compressed rootfs. Once init script will discover correct ext2 partition, it will use it as overlay on top of this squashfs image to make OS image writeable and boots the system using this overlayed filesystem. During boot it also checks whether overlay is on SD is empty (for example because card died) and if so, looks for the backup on harddrive and if found, it is used to populate overlay. So the idea is to use SD card, but backup everything and make a recovery in case SD card dies as easy as possible – you just get a new card from nearest convenience store, unpack an archive on it and boot up. Can’t be simpler I guess.
Little about why choosing squashfs and overlayfs on top of it. SD card is pretty small, and having compressed filesystem will make it much easier to fit. And also, I played with it some time ago and thanks to compressed rootfs device can actually read from it faster as SD cards are slow, but decompression is easy and fast.
If you want to see it or want to try my approach, I put sources to my GitHub repo. It has some implicit dependencies I was too lazy to enumerate and I should write some documentation, but it should download kernel and busybox sources, compile everything, download openSUSE JeOS and Raspberry binary blobs, put everything together and produce
SD directory with files to put on SD card. Just for convenience, I will temporally provide binary archive that you can just unpack to SD card and test. Currently it is really just booting. No ownCloud installed yet, although nginx and php7 are there. It should get IP via DHCP, use HDMI out and you should be able to either ssh to it or login on second console using root account and password owncloud.
What is currently just in TODO is to actually install and play with ownCloud. There is plenty of questions to discuss, like where to put the database and which one. In case of MySQL, we could even divide it and put some tables there and others elsewhere. We have SD, HDD and RAM. Speaking about HDD, also in TODO is to find, format and mount USB drive. That’s also about customizing the final rootfs. Last thing that I would like to do at some point is to try to have an easy way how to recompress the system after updates/additional installs and cleanup the overlay. But that is far future. This post is mainly for people playing with PiDrive to explain which way I’m going and pointing everybody to my GitHub repo 🙂
I got my Raspberry Pi 2 booting from SD card and automatically repartitioning it and it’s easy to deploy, just unpack this archive on SD card with FAT. Sources are at my GitHub, so you can take a look at what it does. No ownCloud installed yet. Root password is owncloud.