Mounting SSD as /mnt/data on a raspberry pi 4

I’m running BalenaOS on a Raspberry Pi 4 (4 GB). I’m running InfluxDB and Grafana via a dockercompose file, with named volumes. This all works, but I would like to store the database on an external SSD (/dev/sda1). Since the named volumes are written to /mnt/data it would make most sense if I could mount my ssd instead of a partition on my SD card.

Alternatively I could mount the SSD only in the InfluxDB container, but that would be less ideal, because then the Grafana data cannot be written to it. I did read the article on mounting persistent storage: https://www.balena.io/docs/learn/develop/runtime/#mounting-external-storage-media but i’m not sure if I can do that from within my docker-compose file, since bind mounts are not allowed.

Any help would be appreciated.

Christian

HI, as mentioned here https://www.balena.io/docs/learn/develop/runtime/#mounting-external-storage-media, you can mount it using Udev rules to a single container and use it to write the influxDB data. Sharing mounted devices across containers is not possible yet, we are working on the feature.

Hmm, would it be possible to have all of BalenaOS running from the SSD? I think the Raspberry Pi 4 does not support booting from a USB SSD device, but this article: https://jamesachambers.com/raspberry-pi-4-usb-boot-config-guide-for-ssd-flash-drives/
has a section:“USB Boot Instructions” that shows how you can boot from the SSD, and then mount root on the SSD. It changes the /boot/cmdline.txt file to point to the right root partition, but this file does not appear to exist in the BalenaOS /boot partition. I would like to run as much of BalenaOS (and certainly the persistent storage) from the SSD, because it is much faster and has less chance of corruption.

Hi, at the moment we don’t officially support booting from an SSD. That said, some users have had success in the past with a few tweaks. Check out this thread for example: Can't boot from USB SSD?. If you attempt it we would love to hear the outcome as this is a feature that we might streamline in the future and any input is valuable.

As a side note, while it’s true that an SSD is a more stable and reliable solution, you can rest assured balenaOS does minimal writes to the SD card (it’s a read only rootfs, https://www.balena.io/os/docs/architecture/#Stateless-and-Read-Only-rootFS) in order to minimise potential corruption problems. This combined with a good quality SD card (we recommend SanDisk extreme pro) yields excellent results.

If you are interested in an off the shelf solution for commercial products you can check out our very own balenaFin (https://www.balena.io/fin/), which is a professional carrier board for Raspberry Pi 3 compute module. One of the design goals of the fin was to solve problems such as SD unreliability.

Thanks, I looked at that thread, but it might be specific to Pi 3’s, because those actually supported booting from USB. With the Pi 4 and Raspbian, you have to do a workaround where you boot from the SD, but mount the SSD as root.

BalenaFin looks like a cool product.

I appreciate that balenaOS does minimal SD card writes, that is why I originally was looking into just having /mnt/data running on the SSD, and keeping the SD card for booting. I am planning to write lots of data to InfluxDB, and would rather not do that on the SD (also for performance reassons)

Here is my current config:

root@balena:~# lsblk -f

NAME FSTYPE LABEL UUID MOUNTPOINT
sda
`-sda1 exfat Samsung_T5 D435-B255
mmcblk0

|-mmcblk0p1 vfat resin-boot 4350-F2E7 /mnt/boot

|-mmcblk0p2 ext4 resin-rootA 667c718d-484d-4cb7-b5d7-6ce2311b5c8a /mnt/sysroot/active

|-mmcblk0p3 ext4 resin-rootB 8ac0a87d-a805-4dcf-8e15-b7c78255eb56

|-mmcblk0p4

|-mmcblk0p5 ext4 resin-state f9d691ed-dbd4-482c-9c5c-fd34f576ec80 /mnt/state

`-mmcblk0p6 ext4 resin-data c7ba12ee-8207-475e-9790-6b2d7d9c980b /mnt/data

root@balena:~# blkid
/dev/mmcblk0: PTUUID=“5ed25e60” PTTYPE=“dos”

/dev/mmcblk0p1: LABEL=“resin-boot” UUID=“4350-F2E7” TYPE=“vfat” PARTUUID=“5ed25e60-01”
/dev/mmcblk0p2: LABEL=“resin-rootA” UUID=“667c718d-484d-4cb7-b5d7-6ce2311b5c8a” TYPE=“ext4” PARTUUID=“5ed25e60-02”
/dev/mmcblk0p3: LABEL=“resin-rootB” UUID=“8ac0a87d-a805-4dcf-8e15-b7c78255eb56” TYPE=“ext4” PARTUUID=“5ed25e60-03”
/dev/mmcblk0p5: LABEL=“resin-state” UUID=“f9d691ed-dbd4-482c-9c5c-fd34f576ec80” TYPE=“ext4” PARTUUID=“5ed25e60-05”
/dev/mmcblk0p6: LABEL=“resin-data” UUID=“c7ba12ee-8207-475e-9790-6b2d7d9c980b” TYPE=“ext4” PARTUUID=“5ed25e60-06”
/dev/sda1: LABEL=“Samsung_T5” UUID=“D435-B255” TYPE=“exfat” PARTUUID=“3300d2f9-01”

I would like to use /dev/sda1 for /mnt/data
How can I do that?

Thanks

Christian

hey there,
That is currently not possible. I have created an issue and if we ever implement this, we will let you know.

I see you have already looked at the docs here
Did you try the steps listed there?
That is using Privileged container + UDEV , then mount the ssd at your desired mounting point. Only that container would be able to access it though.
Does it work for your use case?

Thanks

Thanks, I’m working through the steps. I was able to get a manual mount working from within the container after setting it to privileged. One thing I’m unclear about related to the UDEV rules, if it is only gets executed if I plug the external USB SSD in after the container is running, or if it will mount at container startup (like /etc/fstab) ?

Hi Cristian,

We’ve been talking about it here and we think that the right way to go about this until we have official support in balenaOS for this feature (which is something we’re working on) is to put UDEV rules in the config.json like in this example to ensure that the device is available and ready to be used when your device starts up, and then make mounting the filesystem the first thing that your privileged container does on startup.

Let us know how you get on.

Thanks,
James.

Thanks, l will do that, and report back when I have it all figured out.

I’m struggling with how to automatically mount my external disk inside my container.

My docker-compose.yml looks like this:

version: ‘2’
services:
influxdb:
image: influxdb:latest
ports:
- ‘8086:8086’
privileged: true
And this runs fine. If I ssh into my container, I can run:

mount -t ext4 -o rw /dev/sda2 /media/influxdata

And it will mount the sda2 correctly. But what I cannot figure out how to mount it automatically in my container. The comments above about config.json seems to be for the host OS, not the container.

I tried changing the image in the compose file to a build:

build: ./influxdb

And then create a Dockerfile in the influxdb folder like this:

FROM influxdb:latest
COPY entrypoint.sh /
RUN sed -i ‘s|/var/lib/influxdb|/media/influxdata/influxdb|g’ /etc/influxdb/influxdb.conf
ENV UDEV=1
CMD [“influxd”]

By taking the entrypoint.sh from my container and adding the mount command in it, but if I do that the container never starts. It gives this message forever:

[Logs] [5/16/2020, 11:48:29 PM] Starting service ‘influxdb sha256:cdc81b8263b7d2c1cfc2f394307449221afb39087afb88958ef433018a1b0d21’
[Logs] [5/16/2020, 11:48:33 PM] Starting service ‘influxdb sha256:cdc81b8263b7d2c1cfc2f394307449221afb39087afb88958ef433018a1b0d21’

So what is the best way to mount the partition in the container?

Thanks

Hi

If you go through the documentation here - https://www.balena.io/docs/learn/develop/runtime/#mounting-external-storage-media - you will see that this is about mounting external media inside a container. Adding ENV UDEV=on to your container’s Dockerfile will ensure that the host os transfers the relevant events to the container in question.

So mount and udev rules is the way to go for what you want to do - mount external storage inside of a container - either automatically or manually. See the same docs above on how to do it automatically as well (by using bash scripts)

In case anyone else comes across this thread wanting a way to share a single external-storage filesystem across multiple containers: One approach I’ve gotten to work, though it has tradeoffs and is an ugly hack, is to use NFS mounts. Install the NFS server components in one container, mount the external device’s filesystem there, and export it via NFS. Then in the other containers, install the NFS client components and mount the filesystem using the first container as the NFS server. The containers need to run privileged for this to work.

It would obviously be far preferable to have an officially-supported way to mount the external filesystem on the host and then point multiple containers at the mount point, but if you can live with its downsides, cross-container NFS is at least an option to consider.