Run script on boot

Hey everyone!

We’re running BalenaOS on some of our production devices and we’re trying to figure out how to run a script on boot. Specifically, we want to run curl <some endpoint> each time our device boots to get notified whenever a device comes online.

More generally, we’re also curious whether it’s possible to add additional systemd units. It would be great if we could add some static binaries to /resin-data and have those started and managed by systemd.

Are either of these use cases supported?

Thanks!

Hello,
You could run a shell script at the end of your Dockerfile that includes the commands you want to run on boot, as outlined in this thread: Custom Boot Action/Script - There is also some information there about using systemd as well. Please note that running “on boot” may not be the same as “coming online” so if these suggestions do not achieve what you are looking to do, just let us know.

We added a custom service into our build of the balenaOS image. This might be usefull for you, too.

Caution, building your own balenaOS image, is a little bit more difficult, since it contains working with the yocto project and definitely has a steep learning curve. Make sure that you have enough computational power and free diskspace. Building these images can take multiple tens of GB and run for hours!

We are using the jetson-nano, therefore replace balena-jetson by balena-{platform} that you are using.

The following guide is base on this repository

Create the following folder structure, that will contain all your code:
./layers/meta-balena-jetson/recipes-bsp/my-startup/my-startup/

Place a file containing your service here:
layers/meta-balena-jetson/recipes-bsp/my-startup/my-startup/my-startup.service
Reference on writing a service systemd, building a oneshot service might be suitable for you :slight_smile:

Create a .bb file that tells the build root system what to do here layers/meta-balena-jetson/recipes-bsp/my-startup/my-startup.bb

EXTRAPATHS_prepend := "${THISDIR}/${PN}:"

inherit systemd

DESCRIPTION = "Add your description here"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = " \
    file://my-startup.service \
"

SYSTEMD_SERVICE_${PN} = "my-startup.service"

RDEPENDS_${PN} = " bash systemd"

S = "${WORKDIR}"

do_install () {
    install -d ${D}/${systemd_unitdir}/system
    install -m 0644 ${WORKDIR}/my-startup.service ${D}/${systemd_unitdir}/system/my-startup.service
}

COMPATIBLE_MACHINE="jetson-nano"

Append the build instruction with your service layers/meta-balena-jetson/recipes-core/images/resin-image.inc

IMAGE_INSTALL_append_jetson-nano = " \
    my-startup \
"

As a site note, it might be use full to add curl to the IMAGE_INSTALL_append_jetson since it might not exist in the balenaOS :wink:

I’ve seen the solution of adding a script to entrypoint, but that doesn’t quite seem ideal. Restarting the container would rerun the script.

Building BalenaOS seems fun but it seems like a heavy solution for us. None of us really want to dive into Yocto.

Is there a way to just place a script in /resin-data and then run that? That would really be ideal.

Hi,

By ‘Is there a way to just place a script in /resin-data and then run that? That would really be ideal.’ do you mean from the container into the volume on the host and get the host to run the binary on startup? Unfortunately we don’t support this type of functionality.

Alternatively, if you don’t wish to build your own version of balenaOS, then installing systemd into a container sounds like the best way forward. It’s actually not very difficult to do, here’s an example built for balena which installs both systemd and avahi: https://github.com/balena-io-playground/avahi-zoo-publisher/blob/master/avahi-publisher/Dockerfile.template

The important points to note are that are the masking of irrelevant/potentially problematic services and the setting of the correct STOPSIGNAL. The Dockerfile also copies and enables a unit file to enable its use by systemd. You’ll either need to run the container in privileged mode or note the capabilities, security options and tmpfs mount here: https://github.com/balena-io-playground/avahi-zoo-publisher/blob/master/docker-compose.yml#L6 for a multicontainer project.

Best regards,

Heds