How to get application's config.json into a flasher image?

We have build a custom Yocto flasher image for an RPI 4B prototype, which uses the USB mass storage boot functionality added in the last EEPROM update from RPI. This was done in anticipation of our CM4-based board which will also use a flasher image to get Balena OS on to the EMMC. The flasher is working - it successfully boots up the flasher image, and flashes our Balena OS build to a SD card that is in the PI - emulating the process we will use for the EMMC module on the CM4. The issue I am having is how to get the application’s config.json into the flasher image - or rather, the Balena OS image within the flasher image. I was able to (tediously) do this manually by extracting the Balena OS image (that resides in /opt on the flasher image) and inserting it, but there must be a better way?

Since we are building and compiling our own images in Yocto, I was hoping that we can just place the config.json in the right place so that it is picked up in the Balena OS image build and our devices have wifi access / the correct application ID on startup. I’m just trying to understand if I need to write a custom bb recipe for this, or if the functionality already exists for flasher images, as we can’t be the first ones to run into this issue…

Hello folks,
A bit of background here, balenaOS at build time doesn’t have a config.json file in it and it’s called unmanaged OS which are available here to download on . When you download an image from the balenaCloud dashboard though, you get a managed OS. The imagemaker on the backend takes an unmanaged image of the version you requested for the deviceType you are adding and injects the application’s config.json into it. Making it managed OS for you to download and boot the device from it. From what I understand you aim to do is, with your flasher image you want to flash a managed balenaOS onto the SD card.

To inject the configuration in an unmanaged OS, I can wholeheartedly recommend balenaCLI’s balena os configure command - balena CLI Documentation - Balena Documentation . I personally use it quite a lot in my daily workflow. But, I am not sure how it would work in your case considering you have a custom flasher image around balenaOS but worth a try. Hope it helps you out, let us know if it does. Thanks!

@vipulgupta2048 thank you for the reply. I’ve manage to successfully get config.json and resin-wifi-01 (wifi connection details) on to both the flasher image and the underlying OS image (the image that the flasher flashes to the device). While the wifi works (both the flasher and the OS image have wifi connectivity on boot) the config.json is not taking on the OS image. I’m guessing that os configure is doing more than just dropping config.json in the boot folder. Further, as I’m learning more about your architecture, it seems you use apiKey from config.json as a unique identifier for new devices being provisioned. Because we are planning to use the flasher as a “master key” to flash multiple devices, I’m guessing that we can’t re-use one static apiKey for our flasher, as balena cloud would then have no way to differentiate them.

The functionality we are trying to achieve with the flasher is that each device it flashes shows up as a new device in balena cloud. Even if you flash the same piece of hardware twice, the second time it would show up in balena cloud as a new device that is online, and the first device would report as being offline. Presumably to do this I need to actually have the flasher image use balena-cli to first login (which is fine, as the flasher image has wifi connectivity), and then run os configure right before it actually flashes the hardware to get a new apiKey for the device?

Just want to post some further updates / questions to this thread:

  • With balena-cli, is os configure the same thing as running config generate followed by config inject?
  • config generate generates wifi details as part of the output config.json file, but I’ve read that config inject does not properly setup the wifi connection on the target device when wifi details are provided in config.json format as this is a deprecated methodology - does anyone know if this issue been resolved?
  • If we have a custom image that uses a custom device type (i.e. raspberrypi4-abc) which is essentially the same as raspberrypi4-64 (it extends this image with additional BSP support), how do I use os configure or config generate to convert it to a managed OS? Both require the specification of a device type - and they will not accept raspberrypi4-abc as it is not recognized. And if I set them up using raspberrypi4-64, they are not showing up in my dashboard…

Hi there, looking at the parameters for each, balena config generate ..., generates the full config file, while balena os configure ... and balena config inject ... broadly achieve the same result by adding the config to the OS image, though one operates on a mounted file system level while the other on the file image level. It may be that one uses the other internally and we expose both for flexibility. I personally always use config generate followed by os configure.

In relation you the custom DT, if you pass in --deviceType generic-aarch64 flag to config generate, edit the generated config.json, replacing "deviceType": "generic-aarch64", with the value of your DT slug and place this config into the flasher image, you should be able to achieve what you need.

This process will generate a new API key for the device to register with the API every time.

But actually, you are right about inject not handling the NM profiles, there is an issue currently open against the CLI project to address this.