I have an application that runs on a RPi 3. This application can update itself by checking for a new version on a web server. If there's a new version, it downloads it from the server, runs a contained installation script, then reboots and the user is good to go.

My problem is that as the application evolves, there are many more linux and python packages and configuration changes that are required, and managing all the different versions is extremely difficult. Not to mention, larger upgrades take a long time and if the user shuts down or otherwise interferes during the upgrade, it could break the application.

I'm trying to figure out a better way of doing things here. I know one way would be to have images that are installed. In other words, I have an image I create, they use that exact image and then there's no chance of anything breaking. But is it possible to download and install a new RPi image remotely, or is this something that can only be done with a device (usb, sd)? If this isn't possible, is there some other better practice for something like this?

  • 1
    This is what the package system is for. If user interference during the upgrade is a problem then you could add a layer at startup that checks if the last upgrade succeeded. – Tomas By Mar 27 at 16:24
  • When you say package system, are you talking about apt? In other words, check if all the necessary packages are installed on startup and if not, install them? – Ryan Bobrowski Mar 27 at 16:41
  • 1
    Well, I meant the case where an upgrade is aborted by the user (eg by disconnecting the power). You could check for this at startup to avoid trying to run an inconsistent installation. – Tomas By Mar 27 at 16:59
  • Right, thanks. I'm thinking after installations are complete a file is saved somewhere indicating that that version was successful. – Ryan Bobrowski Mar 27 at 17:02

The common way of doing this is having two sets of partitions. Initially, they are identical (modulo mount points in their corresponding grub and fstab configs). Call one the active set and the other the standby set. When new versions of anything are available, install them in whatever way you want on the standby set. If it gets corrupted because of a crash, or whatever, simply recreate it. When the update process is happy that everything is good on the backup set, run grub-update to change the boot partition to the one of the standby set, and reboot. Now the standby set has become the active set, and vice versa.

There is always a small failure window, namely, while the boot sector is being rewritten. You cannot avoid that. Devices that use similar mechanisms to make sure updates do not corrupt the boot media (pretty much any piece of consumer electronics that can upgrade itself over the air does something similar) have some sort of firmware support so that flipping a single bit in an EEPROM tells them where to boot from next, but I don't think you can actually modify the GPU boot code of the Pi to have such functionality.

  • Good answer, but a point of confusion for me: Is grub required to use this 'modulo mount point' feature? – Seamus Mar 28 at 0:23
  • Assuming you have a set /dev/mmcblk0p1 with /dev/mmcblk0p2 and set /dev/mmcblk0p3 with /devmmcblk0p4/: how to boot from /dev/mmcblk0p3? – Ingo Mar 28 at 9:44

Your Answer

