{"id":41121179,"url":"https://github.com/raspberrypi/rpi-system-update","last_synced_at":"2026-06-17T11:31:41.896Z","repository":{"id":135246751,"uuid":"541642563","full_name":"raspberrypi/rpi-system-update","owner":"raspberrypi","description":"System update scripts","archived":false,"fork":false,"pushed_at":"2024-03-01T17:51:08.000Z","size":22,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-03T14:56:17.817Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raspberrypi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-26T14:59:23.000Z","updated_at":"2025-07-27T21:21:38.000Z","dependencies_parsed_at":"2025-02-25T05:26:57.328Z","dependency_job_id":"abeb1ab2-04c0-4e64-8be5-4616d56b68ae","html_url":"https://github.com/raspberrypi/rpi-system-update","commit_stats":null,"previous_names":["raspberrypi/rpi-system-update"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/raspberrypi/rpi-system-update","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Frpi-system-update","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Frpi-system-update/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Frpi-system-update/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Frpi-system-update/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raspberrypi","download_url":"https://codeload.github.com/raspberrypi/rpi-system-update/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Frpi-system-update/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34447264,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-22T17:33:03.716Z","updated_at":"2026-06-17T11:31:41.890Z","avatar_url":"https://github.com/raspberrypi.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Raspberry Pi System Update\n\nJust enough buildroot to run docker applications from a light weight\nOS wrapper providing verified boot, A/B booting, updates and file system\nencryption.\n\n## Intro\nThe high level approach is to have a single file boot ramdisk that contains\na bootable Linux initramfs that is capable of updating itself and installing\nan application component. This image can be signed for secure-boot and\nlaunched using the Raspberry Pi 4 (or newer) network-install feature in the bootloader.\n\nThe application component is installed to a local block device (e.g. MMC). \nTypically, a self-updating service such as docker would be used as in this example\nhowever, it should be straightforward to replace docker with other solutions.\n\nSee https://github.com/timg236/buildroot/tree/rpi-system-update\nfor the buildroot packages and defconfig.\n\nThe software update process is separate from the component which downloads\nnew updates to install.  For simplicity, this example uses scripts `curl` to download updates.\n\n## Goals\n* Runs on Raspberry Pi 4 and Pi 5 family.\n* Minimal patches to core buildroot.\n* Easy for users to customize the setup scripts as desired e.g. custom docker setup.\n* Easy to verify / understand security model.\n* Replacable FOTA model (for when wget isn't enough!)\n\n## System software\nThe system-software in the boot ramdisk contains:-\n\n* Linux Kernel\n* Device-tree overlays\n* initramfs containing modules and software required to install and launch\n  the application component (e.g. Docker)\n* A RSA public key used to verify updates.\n* Raspberry Pi GPU firmware (aka start.elf) for Pi4 family.\n\n### Secure-boot\nThis package shows how signed boot images can be used to securely provision and upgrade the system.\nPlease see the [secure-boot](https://github.com/timg236/usbboot/blob/master/secure-boot-example/README.md)\ntutorial for more information about how to enable secure-boot in the bootloader.\n\nThe `rpi-system-update` package also implements an option (`BR2_PACKAGE_RPI_SYSTEM_UPDATE_ENCRYPT_APPLICATION_FS`)\nto encrypt the application file-system using LUKS and a private key stored in the OTP.\nThe key must have already been programmed e.g using the `rpi-otp-private-key` utility in the usbboot repo.\n\n**IMPORTANT:**\n* Since this is an example UART login is enabled in order to debug / experiment with the update scripts.\n  In a production system this should be disabled when deciding what if any remote access should be permitted.\n\n## Architecture\nThe system consists of four main components:-\n\n* The application image - installed to an SD card (or build time configurable block-device).\n* A network install `boot.img` that can be launched via the Raspberry Pi bootloader. This downloads the full application image to a blank SD card.\n* A bootloader EEPROM image configured to download the net-install release from the web server.\n* A web-server hosting the latest application image updates (`boot.img` and `boot.sig`) files plus version manifest file.\n\n### Kernel / Firmware\nThis system uses the latest (rpi-update master) kernel and firmware releases and no custom configuration is required.\n\n### cmdline.txt / config.txt\nTo customize the firmware `config.txt` or `cmdline.txt` edit the files under `board/raspberrypi-system-update`\n\n### Installation flow\n\n1. The Raspberry Pi bootloader is updated with a custom EEPROM image containing the network install configuration.\n2. User powers on the Raspberry Pi holding down a push-button attached to a GPIO.\n   * This triggers [GPIO conditional filter](https://www.raspberrypi.com/documentation/computers/config_txt.html#the-gpio-filter) in the EEPROM config to go into network install mode.\n3. The network install `boot.img` is downloaded into RAM and executed.\n4. `rpi-system-update` is launched via systemd in `install mode`.\n5. `rpi-system-update` waits for the block device specified in `/etc/default/rpi-system-update` to appear. It then creates the file-system.\n6. `rpi-systme-update` downloads the `version` and `version.sig` files specified in `/etc/default/rpi-eeprom-update`.\n7. `rpi-system-update` verifies the authenticity of `version` + `version.sig` using the public key specified in `/etc/default/rpi-eeprom-update`. If the verification fails then the version files are downloaded again.\n8. `rpi-system-update` downloads the compressed `boot.img.gz` specified in the version file and the corresponding signature file.\n9. `rpi-system-update` decompresses the `boot.img.gz`, verifies the signature. If the signature matches then the `boot.img` is decompressed and installed to either `/boot/boota` or `/boot/bootb` depending on whatever partition is the active partition (the one the system booted from. The inactive partition is referred to as the `TRYBOOT partition`.\n10. `rpi-system-update` triggers a reboot.\n11. The EEPROM bootloader boots from the specified block device (since the system-update GPIO button has been released).\n12. The bootloader loads `boot.img`, checks the signature if secure-boot is enabled then starts booting.\n13. `rpi-system-update` is run in `application mode`. If the local file-system is blank then it is formatted as Linux and configured for the specified docker service. Otherwise, it is just mounted and docker starts as normal.\n\n### Update flow\n* `rpi-system-update` is run in `download mode` from a systemd timer.\n* If a newer version is available it is downloaded if an upgrade is NOT already pending\n* After verifying the authenticity of the download `rpi-system-update` copies the new image to the `TRYBOOT partition`\n* `rpi-system-update` sets a flag (a file) indicating that there is a pending update ready to be tested.\n* When the system is next rebooted the `rpi-system-update` will apply the upgrade.\n\n### Upgrade flow\n* `rpi-system-update` is launched by systemd `upgrade mode` early during boot.\n* If a `tryboot` upgrade is pending then `rpi-system-update` clears the update-pending flag and runs `sudo reboot \"0 tryboot\"` to reboot into `tryboot` mode.\n* If the system is already in `tryboot` mode then the update was successful so `/boot/auto/autoboot.txt` is modified to swap the active/tryboot partitions.\n* The system is rebooted into the new `active partition.`\n\n###  Buildroot packages\n\n### rpi-system-update\nThis package installs [rpi-system-update](https://github.com/timg236/rpi-system-update) scripts and systemd services.\nThe package config provides various configuration options so that `/etc/default/rpi-system-update` can be automatically generated from the buildroot defconfig.\nSee `BR2_PACKAGE_RPI_SYSTEM_UPDATE_*` options in \"make menuconfig\"\n\nFor DEBUG ONLY, this package also creates a user called 'admin' with SSH access. Password authentication is\nnot enabled, instead define the `authorized_keys` files to be written to `/home/admin/.ssh/authorized_keys`\n\n### raspberrypi-secure-boot\nThis package installs the `secure-boot` scripts from the [usbboot](https://github.com/raspberrypi/usbboot) to support signing of boot images.\n\n### rpi-firmware\nThere are some minor enhancements to this package.\n\n* Make it easier to select a custom command line and `config.txt` file from the buildroot board config files.\n* Install the overlays to the initrd image to support runtime dtoverlay configuration from the userspace in an initrd.\n\n## Building\n\n### Git clone\n\n```\nmkdir -p rpi-buildroot-dev\ncd rpi-buildroot-dev\ngit clone --branch rpi-system-update https://github.com/timg236/buildroot buildroot\ngit clone --branch rpi-system-update https://github.com/timg236/buildroot buildroot-net-install\ngit clone --branch rpi-system-update https://github.com/timg236/rpi-system-update rpi-system-update\n```\n\n### Configuration\nBefore building the buildroot image the signing keys, and update server information must be defined.\n\n```\ncd buildroot\nmake raspberrypi-system-update_defconfig\nmake menuconfig\n```\n\nGo to `Target packages --\u003e  System Tools --\u003e rpi-system-update`\n\n**Public key**  \nThe path of the public key .PEM file must be supplies so that it can be embedded in the image file. This is used to check the authenticity of newer versions of the image.\n\n**Private key**  \nIf a private-key file is specified then the this will be used to automatically sign the image file. Alternatively, leave this blank to create an unsigned image. That might be desirable if the private is stored in a TPM and you want to sign the images on a separate secure server.\n\n**Update URL**  \nThe URL of the `version` file that `rpi-system-update` will poll for updates.\n\n**Version number**  \nThe version number is simply an integer defined by `BR2_PACKAGE_RPI_SYSTEM_UPDATE_VERSION` and embedded in `/etc/default/rpi-system-update`.\nAfter updating the version number the `rpi-system-update` package must be rebuilt.\n\n* The `rpi-eeprom-update` script never downgrades to a lower version number.\n* Version numbers do not describe API compatibility.\n\n### Build the image\n\n```\ncd buildroot\nmake raspberrypi-system-update_defconfig\nmake\n```\n\nOutput files:-\n* output/target/images/boot.img.gz\n* output/target/images/boot.sig\n\nThe output images can be copied to the download server and the `verison` file update.\n\n#### Configuration updates\n**Rebuilding after a configuration change**\n```\nmake raspberrypi-system-update_defconfig \u0026\u0026 make rpi-system-update-reconfigure \u0026\u0026 make\n```\n\n### Building the network-install image\nThe network-install image is optimized for size (32-bit kernel) and needs to be built in a different tree.\nHowever, it's unlikely that this would need to be updated frequently because it's sole purpose is to\ndownload and install the real `boot.img`.\n```\ncd buildroot-net-install\nmake raspberrypi-system-update-net-install_defconfig\nmake\n```\n\n#### Configuration\nConfigure the public key, private key and update URL. The version number should be set to 0 since the initial install just calls the update routine.\n\nOutput files:-\n* output/target/images/boot.img\n* output/target/images/boot.sig\n\n### Bootloader EEPROM\nThe following EEPROM configuration shows how a GPIO conditional filter may be used to start an automated network install image.\n\nExample `rpi-system-update/server/boot.conf`\n\n#### SIGNED_BOOT\nIf `secure-boot` is enabled in OTP then the contents of the `boot.img` file is always verified using the EEPROM public key. If secure boot is not required then `SIGNED_BOOT` can be placed within the GPIO conditional section so that the signature is only checked for the network install step.\n\nReplace `update.raspberrypi.com` with the domain name of your software update server.\n```\n[all]\nBOOT_UART=1\nHDMI_DELAY=0\nWAKE_ON_GPIO=1\nPOWER_OFF_ON_HALT=0\n\n[gpio2=0]\n# There is currently no support for custom CA certs so HTTP only for now.\n# version.sig and boot.sig verify authenticity.\nSIGNED_BOOT=1\nBOOT_ORDER=0xf7\nHTTP_HOST=update.raspberrypi.com\nHTTP_PATH=rpi-system-update/net-install\n```\n\nTo generate `rpi-eeprom-recovery.zip` run\n```\nmkdir -p update-server\n./rpi-system-update/build-eeprom update-server\n```\n\nTo use a different EEPROM image specify the filename in the `RPI_EEPROM_IMAGE` environment variable.\n\n### Adding a release to the download server\nThe `rpi-system-update/server/add-release` script can be used to create populate a new directory in the suitable structure from images built from buildroot.\n\nEdit `rpi-system-update-server/config` to specify the base URL to include\nin the `version` file.\n\nAdd release version 2 to the update-server directory.  \n```\nmkdir -p update-server\n./rpi-system-update/server/add-release update-server 2\n```\n\nUpdate the net-install images from the buildroot-net-install  \n```\nmkdir -p update-server\n./rpi-system-update/server/add-release update-server net-install\n```\n\nExample `version` file - replace with your HTTP (not HTTPS) server name. \n```\nversion: 2\nsignature-url: https://update.raspberrypi.com/releases/1/boot.sig\nimage-url: https://update.raspberrypi.com/releases/1/boot.img.gz\n```\n\n### Application configuration\nThe HomeAssistant docker-application is a real world example to verify the\ninstallation and launching of applications in an encrypted disk. Docker \napplications also benefit from Docker's built in install / OTA mechanism\nat the application.\n\nThe docker service is selected by defining `BR2_PACKAGE_RPI_SYSTEM_UPDATE_DOCKER_APPLICATION` e.g. `home-assistant`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspberrypi%2Frpi-system-update","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraspberrypi%2Frpi-system-update","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspberrypi%2Frpi-system-update/lists"}