[Tutorial] Odroid C4 rootfs on USB drive

When using a board like the Odroid C4 as a (production) server, you want to limit the usage of the sdcard as much as possible. There are (for me) two reasons for that:

  • sdcards have limited read / write cycles: so especially on a server that runs 24/7 the sdcard will quickly wear down and fail.
  • performance of sdcards is (very) low: when running a server, disk speed is important. sdcards will slow down your whole system.

As the Odroid C4 requires an sdcard (or eMMC) to boot from (it lacks build in SPI flash memory that you can use to boot from), you still need the sdcard for booting (which is okay as this is a one time event and not a continues read / write event). But you want the rootfs NOT on the sdcard, you want that to come from a USB drive (as the Odroid C4 doesn’t have SATA ports and only USB ports).
There are several guides on the internet describing how to achieve this, but not all of them are working (obsolete) or are not working with DietPi (as DietPi made the decision to ‘abandon’ the separate boot and rootfs partition, and not only has one partition: the rootfs partition)

This guide will help you in running you Odroid C4 with DietPi from a USB drive.

pre-requisites

  • (ext4) formatted usb drive.
  • rsync installed.
  • some basic linux sysadmin knowledge between chair and keyboard.

Install Odroid C4 with DietPi following the DietPi instructions until you have a configured and running setup that you can log into using ssh.

Instructions

  1. ssh into your Odroid as root user
  2. insert the usb drive
  3. get the UUIDs for the attached disks (both USB drive and sdcard):
    lsblk -f
  4. mount the usb drive (assuming it is sda1, otherwise replace with correct one):
    mkdir -p /mnt/usb
    mount /dev/sda1 /mnt/usb
  5. copy the entire sdcard contents into the usb drive:
    rsync -axv / /mnt/usb/
  6. empty the boot directory on the USB drive (!), and create (future) sdcard mount directory:
    rm /mnt/usb/boot -rf
    mkdir -p /mnt/usb/sdcard
    ln -s /mnt/sdcard/boot /mnt/usb/boot
  7. edit fstab (on USB drive!) to load the correct mountpoints after booting from the USB drive:
    nano /mnt/usb/etc/fstab
    > under section ‘# PHYSICAL DRIVES …’ replace the entry for the / mount point and add the /mnt/sdcard mount point
    UUID=[... your usb drive UUID ...] / ext4 noatime,lazytime,rw 0 1
    UUID=[... your sdcard UUID ...] /mnt/sdcard ext4 noatime,lazytime,rw,nofail,noauto,x-systemd.automount
  8. edit the dietpiExt.txt:
    nano /boot/dietpiEnv.txt
    > change the entry for rootdev to hold the UUID for your USB drive
    rootdev=UUID=[... your usb drive UUID ...]
    > add rootdelay=30 to the variable extraargs
    extraargs=rootdelay=30 net.ifnames=0
  9. reboot your device and keep fingers crossed:
    reboot now

What have we just done?
So we still need the sdcard for initiating the bootprocess, for that we require the /boot directory.
Upon boot we set the root directory to the USB drive (and by doing that we ‘overwrite’ the boot directory with the (empty) one on the USB drive), we work around this by using a bind mount point: the /boot directory on the USB drive (which we made empty) is mounted from the /boot directory of the sdcard.
This way, we only have one /boot directory: the one on the sdcard. Every change made by scripts / installs / configurations etc. made on the /boot directory will be available on actual boot as the /boot directory after booting is actually the /boot directory on the sdcard.
Because USB drives take time to initialize we need to tell the kernel that before it loads, it should wait (e.g.) 10 seconds before trying to load the rootfs. This should be enough time for the USB drive to ‘spin up’.
As we do not want to change (and compile) the /boot/boot.cmd file to add the rootdelay=10 parameter, we use the DietPi built-in dietpiEnv.txt to add the bootdelay as extra argument passed to the kerel startup parameters. By doing it this way we make sure that we never get into trouble when for some reason an upgrade changes the boot.cmd (and clears out your changes). That said, assuming that the dietpiEnv.txt will never change / overwrite on upgrades.

So there you have it: Odroid C4 booting from your sdcard and faster then ever running from your USB drive.

Feel free to comment and / or share your experiences with this instruction!

5 Likes

20230122:

  • changed bind mount method to more common symlinking of the boot directory
  • changed extraargs variable as this is already set so adding it overwrote it’s initial set value
  • changed the rootdelay value to 30 seconds, as I was seeing that the spin-up of the USB drive was not constant and in some cases 10 seconds was not enough. As this delays the boot only, 30 seconds for me is acceptable (being a server), when using it for another setup feel free to find the optimal value for your setup