Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cywang117/c758a448ddb06e58ce57c2ced9716e73 to your computer and use it in GitHub Desktop.
Save cywang117/c758a448ddb06e58ce57c2ced9716e73 to your computer and use it in GitHub Desktop.
Preload any Supervisor onto balenaOS image

Replace loopN with loop number listed with partx command

Download & mount .img

balena os download raspberrypi4-64 -o rpi4.img
losetup -fP --show rpi4.img
mount /dev/loopNp6 $MOUNTPOINT 

If the mount fails with wrong fs type or similar, this is most likely because the image is a flasher image (i.e. for Intel NUC, for example), and you will need to do the following:

mount /dev/loopNp2 $MOUNTPOINT
cp $MOUNTPOINT/opt/balena-image-genericx86-64.balenaos-img $WORKDIR
losetup -fP --show balena-image-genericx86-64.balenaos-img
mount /dev/loopNp6 $MOUNTPOINT

Change local machine Docker data dir to mounted .img Docker dir

Add the following to /etc/docker/daemon.json, replacing $MOUNTPOINT with your data partition mountpoint:

{
  "data-root":"$MOUNTPOINT/docker"
}
systemctl daemon-reload
systemctl restart docker
docker info | grep 'Docker Root' # Verify data change success

Get and pull your desired Supervisor image

  1. Get the IMAGE_URL using balenaSDK via Chrome dev console
// Replace consts with your desired slug & version
const DT_SLUG = 'raspberrypi4-64';
const SV_VERSION = 'v1.2.3';

await sdk.pine.get({
    resource: 'supervisor_release',
    options: {
        $filter: {
            is_for__device_type: {
                $any: {
                    $alias: 'dt',
                    $expr: {
                        dt: {
                            slug: DT_SLUG
                        }
                    }
                }
            },
            supervisor_version: SV_VERSION
        },
    }
})
  1. Pull image (IMAGE_URL from step 1) from balena registry & export On a local balenaOS device:
balena login registry2.balena-cloud.com -u d_$(cat /mnt/boot/config.json | jq -r '.uuid') -p $(cat /mnt/boot/config.json | jq -r '.deviceApiKey')
balena pull $IMAGE_URL
balena save $IMAGE_URL > /mnt/data/happy-eyeballs.tar
# Copies from local balenaOS device to a local dev machine that accepts scp
scp /mnt/data/happy-eyeballs.tar $USER@$LOCAL_MACHINE:$DIRECTORY
  1. Load Docker image on local machine, replace existing Supervisor image
  • Note the existing Supervisor image ($REPOSITORY, $TAG below):
  • Also note that some OS's will come with a Supervisor image tagged twice, so both tags will need to be removed. Record the SV IMAGE ID to make sure all tags referencing the image are deleted.
docker images                     
REPOSITORY                  TAG        IMAGE ID       CREATED        SIZE
balena/aarch64-supervisor   v12.11.0   b7b6ead1c4b6   2 months ago   72.7MB
  • Remove existing, load new
docker rmi $REPOSITORY:$TAG
docker load < $DIRECTORY/happy-eyeballs.tar
  • Tag new image with all the old image's tags to mask it as old image
docker image tag $IMAGE_URL:latest $REPOSITORY:$TAG

Cleanup & unmount

rm /etc/docker/daemon.json
systemctl daemon-reload
systemctl restart docker
umount /dev/loopNp6 $MOUNTPOINT
losetup -d /dev/loopN

If the OS image is a flasher image, you'll also need to umount and losetup the /dev/loopNp2 (active root partition) that was mounted.

Configure OS img

balena os configure sv_preloaded.img --fleet $YOUR_FLEET
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment