A few years back I purchased a FreedomBox Pioneer Edition HSK (HSK) to use as a dedicated server for various functions. The HSK is built around the Olimex A20-OLinuXino_LIME2 (LIME2) Single Board Computer (SBC) and features a SATA port with an associated power port to support the use of an external disk drive—typically a 2.5" laptop sized drive, either a Hard Disk Drive (HDD) or Solid State Disk (SSD).
The FreedomBox is a software stack built on top of Debian and is intended to be a network appliance for a number of installable apps. From the Web page:
FreedomBox is a private server for non-experts: it lets you install and configure server applications with only a few clicks. It runs on cheap hardware of your choice, uses your internet connection and power, and is under your control.
The “cheap hardware” is always the attractive part as is the size of the Pioneer HSK which is small enough to be tucked away and forgotten until…
Yes, the inevitable occurred—crashes with alarming frequency that led me to finally investigate the issue. As the preferred way to boot and often times run such a system is with a micro-SD card, I found it giving a large number of errors.
Sigh…
Saving and writing the micro-SD image
Recovery seemed a remote possibility so I opted to try and salvage a copy with
dd
as (the mmcblk0
device name is what the kernel assigns to cards inserted
in the internal SD card slot of my laptop. A card inserted into a USB card
reader adapter will be assigned sdx
where x
is the next available letter,
at least this is the case with my hardware):
dd if=/dev/mmcblk0 of=freedombox.img status=progress bs=8192
See man dd
for an explanation of the syntax.
And hoped for the best. I did end up with a 128GB file that likely contains the errors as well but if the card died completely, at least I have that to copy whatever files weren’t corrupted.
The next step was to download a fresh image from the Pioneer Edition FreedomBox Web page and write it to a new micro-SD card which was more or less a reversal of the command above:
dd if=freedombox-stable-free_pioneer_a20-olinuxino-lime2-armhf.img of=/dev/mmcblk0 status=progress bs=8192
Note: dd
is a simple but very powerful program. It won’t warn you if
you’re about to overwrite existing data, either a file or whatever is on the
target device. Take a moment to examine the command line again before hitting
the Enter key. Writing directly to a device file will require root
privileges.
Root partition on a SATA drive
With that done, I booted the HSK with the new image and proceeded through the
initial setup. At this point I contemplated my options for using a SATA
attached drive as the root partition. One option was to “ghost” the root
partition of the micro-SD image to the SATA
drive,
but anyone who has tried wrestling with uboot
knows that pointing it to a
different root partition can be easy or impossible depending on how it was
setup by the distribution at hand. This led me to search the FreedomBox
Pioneer Support forum for
any discussion of using a SATA drive as a root partition on the LIME2
hardware. The following
message gave a
clue in the form of the btrfs replace
command (see the linked bug/issue for
more details). Perhaps this would be the way to get the root partition onto
the SATA drive.
At this point it should be noted that the FreedomBox image contains two partitions. The first is rather small and formatted in the
ext2
file system format. The second is quite a bit larger and is formatted in thebtrfs
file system format. These will be noted asp1
andp2
going forward.
Once the system is booted and running from the micro-SD card, p1
is mounted
under the boot
directory of the root (/
) file system. This is an
advantage for moving the root file system to the SATA drive. According to the
linked post above, the btrfs replace
command held the promise of moving the
root file system from the micro-SD card to the HDD while the system was live
and running. Incredible! This I just had to try.
Left over from some previous project a few years ago. I had two 1 TB HDDs
mounted on a metal tray that would serve as the base for this experiment.
With one of the HDDs attached to the SATA port and powered, I booted the
system from the micro-SD card and logged in from an attached USB keyboard as
I had the HSK connected to it and an HDMI display but was denied running
administrative commands with sudo
.
To back up slightly, the initial FreedomBox setup is done through a Web page
interface (WUI) and the user account that is setup becomes the administrator
of the system. However, I found that logging in through the console (locally
attached keyboard and monitor) does not grant that user access to
administrative privileges through the sudo
command, a bit of a surprise
(Note: later reboots did allow for running sudo
from the console.
YMMV). Yet, logging in as the same user through Secure SHell (SSH) over the
network from another computer does grant those privileges. As the system is
most often run “headless”, i.e. no attached keyboard or monitor, this is not a
big deal but is something to be aware of.
With the system up and running (the fresh image, not my long running one with
errors at this point) and logged into the root account with sudo -i
(easier
as one doesn’t have to remember to prefix every command with ‘sudo
’, I
started the process with the following command:
# btrfs replace start -Bf /dev/mmcblk0p2 /dev/sda /
When complete, the utility closed without printing anything to the console simply returning the shell prompt. There is a way to monitor the progress which will be shown below.
To verify that the root has really been changed, use the df
command:
# df -h
Filesystem Size Used Avail Use% Mounted on
udev 435M 0 435M 0% /dev
tmpfs 100M 3.5M 96M 4% /run
/dev/sda 118G 19G 100G 16% /
tmpfs 496M 24K 496M 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda 118G 19G 100G 16% /.snapshots
/dev/mmcblk0p1 2.1G 56M 1.9G 3% /boot
tmpfs 100M 4.0K 100M 1% /run/user/10000
tmpfs 100M 4.0K 100M 1% /run/user/10001
Indeed, /
now resides on /dev/sda
(Note: btrfs can use the raw disk
device without need of partitioning!)
The next step is to expand the root file system to use all of the available disk space:
# btrfs filesystem resize max /
Resize '/' of 'max'
Not much output so use the df
command again to see the change:
# df -h
Filesystem Size Used Avail Use% Mounted on
udev 435M 0 435M 0% /dev
tmpfs 100M 3.5M 96M 4% /run
/dev/sda 932G 19G 914G 2% /
tmpfs 496M 24K 496M 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda 932G 19G 914G 2% /.snapshots
/dev/mmcblk0p1 2.1G 56M 1.9G 3% /boot
tmpfs 100M 4.0K 100M 1% /run/user/10000
tmpfs 100M 4.0K 100M 1% /run/user/10001
In a lack of foresight I performed the previous steps with the micro-SD card with the errors, but once complete I realized that I was in a bit of a pickle. I had the root file system running from the SATA HDD but the boot partition was still on the micro-SD card with the errors. What to do?
As I had already resized the most recently copied file system to the max of
the drive, I needed to get it to fit into the 29 GB or so available on the
fresh micro-SD card. Well, btrfs
can do that too:
# btrfs filesystem resize 25G /
Resize '/' of '25G'
And confirmed the new size:
# df -h
Filesystem Size Used Avail Use% Mounted on
udev 435M 0 435M 0% /dev
tmpfs 100M 3.5M 96M 4% /run
/dev/sda 25G 19G 6.5G 74% /
tmpfs 496M 24K 496M 1% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda 25G 19G 6.5G 74% /.snapshots
/dev/mmcblk0p1 2.1G 56M 1.9G 3% /boot
tmpfs 100M 4.0K 100M 1% /run/user/10001
tmpfs 100M 4.0K 100M 1% /run/user/10000
Cool, eh?
The next steps I took were to:
- Unmount the
boot
partition and remove the bad micro-SD card. - Insert the fresh micro-SD card.
- Use the
blkid
utility to get the UUID of/dev/mmcblk0p1
and edit/etc/fstab
to reflect that value. - Mount the new
boot
partition.
Now the problem I faced was figuring out how to make the fresh micro-SD card
point to the second root partition instead of the first one. While I am sure
there is a way to modify this value, I was impatient and opted to run the
btrfs replace
command to move the root file system to the fresh micro-sd
card:
# btrfs replace start -Bf /dev/sda /dev/mmcblk0p2 /
ERROR: target device smaller than source device (required 1000204886016 bytes)
Crud. Except I didn’t say, “Crud!” (oblique reference to the movie A Christmas Story).
In my estimation, even though the resize was successful as shown by the df -h
command, the system still had a reference to the partition being 1 TB,
which clearly won’t fit into 29GB no matter what (or a LOT of data
compression). A reboot should correct this little problem. Except that the
next problem reared its ugly head, the reboot failed.
To cut a long story short, the root filesystem from the micro-SD card with
errors carried its UUID throughout the process and the fresh micro-SD card was
looking for a different UUID (the one native to the downloaded image). I
learned this by connecting a serial adapter to the proper pins on the LIME2
board and watching the messages printed to the serial port as the system was
booting. Then I used another btrfs
command (that I have forgotten to note)
to write the UUID the fresh micro-SD was expecting to find for the root
partition into the file system I wanted to use as /
, get the system to start
from the fresh micro-SD card, run the btrfs replace
command to get the root
file system onto the SATA HDD, resize it, and finally make sure it all booted
again. Whew!
Other than my boneheaded mistakes, the btrfs replace
command is a very
clever way to (almost) painlessly get the FreedomBox micro-SD card image’s
root file system onto a SATA HDD.