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.
(ext4) formatted usb drive.
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.
ssh into your Odroid as root user
insert the usb drive
get the UUIDs for the attached disks (both USB drive and sdcard): lsblk -f
mount the usb drive (assuming it is sda1, otherwise replace with correct one): mkdir -p /mnt/usb mount /dev/sda1 /mnt/usb
copy the entire sdcard contents into the usb drive: rsync -axv / /mnt/usb/
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
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
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
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!
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
Still working correct and no adjustments made after 20230122
For anybody stumbling on this tutorial: never mind all the replies below as these are not relevant / related to the tutorial. They do add however some good background info if you can filter that out.
Once I had petitboot running I did the netboot install of debian 11. No sound. I tried deb 12 and had some issues. Went back to 11 and after a few months, a new kernel came out and sound started working!! The desktop still has some glitches where the screen will go black but you can click on stuff and it will refresh properly. Running firefox and watching youtube and browsing is good. I run kodi and a chrome app for tubi as there is no arm support for the video decryption on any browsers
@WarHawk actually it won’t as the guide you linked to is obsolete and although it holds some good background information is deprecated.
The assumption in this guide is that there are 2 partitions: a boot partition (that stays on the sdcard) and the rootfs partition that you can move to the usb disk. But this is not the case anymore hence the need for a new instruction
it was decided sometime ago to only have 1 partition that holds both the boot and root files. This means that the instruction you linked to doesn’t work anymore.
I left the /boot on the SD card, the rootfs (/) on the USB or the SSD…this way on boards that do not have an EEPROM that can be flashed to tell the SBC to boot from another device (such as the USB or SD)
Never understood why they did that…if the partition get’s corrupted it screws up the boot…if it had 2, it would be easier to scan/fix the fat32 partition that contained the kernel and boot parameters…and make it much easier to move the root partition to a faster device
@Joulinar but that is for the HC4 and not the C4, there is a difference in these two. I think (not sure) that the HC4 has a SPI where the C4 doesn’t have that.
Although you could get it to work with petitboot, but that is not as clean as the instruction here imo as that requires an external ‘tool’ (petitboot), so adds maintenance / secutiry / etc.
Only benefit for petitboot I see is if i needed multiple images to boot from, but for me I only need armbian/dietpi so petitboot makes the setup to ‘complex’ and adds no value
or I am missing something that it does add for my use case
As far as i can see, the boot partition is ‘static’ with the exception of the dietpi scripts residing there.
So only writes to the sdcard on updates and on some dietpi scripts writing their (temp) state to a file (which could be on the boot directory: never looked into this).
So the when the sdcard ‘crashes’ it is as simple as restoring an image of the crashed on onto a new one.
Only thing to remember here is to create a backup of the /boot periodically (which should always be done)
Yes, i know, and as said that ‘requires’ petitboot which I do see use cases for but I do not see any added value for my specific use case (I have no use for a bootmanager as I only have one image to boot from).
So the instruction provided here is IMO the easiest and cleanest one without having to find out how to install and maintain petitboot