Comparing Open-Source OTA Update Engines for Embedded Linux
If you are building an embedded Linux product, one of the engineering decisions you face is which on-device update engine to use. This decision has lasting implications: embedded devices routinely have lifecycles of 5 to 15 years, and whichever update mechanism you choose today will determine how you ship software to devices already in the field for the entire duration of that lifecycle.
Fortunately, the landscape of open-source OTA update engines for embedded Linux has matured significantly over the past decade. Where teams once wrote bespoke shell scripts to flash partitions, there are now several ready-made open-source tools available to choose from. These tools differ in philosophy, architecture, features, and the trade-offs they make. In this article, we survey and compare the major open-source OTA update engines for embedded Linux, examine the fundamental techniques and strategies they employ, and provide a technically grounded comparison.
Scope and Methodologyβ
We consider the following open-source update engines, which we believe to be the most widely used and actively maintained solutions in the embedded Linux ecosystem:
- Mender (Northern.tech)
- RAUC (Pengutronix)
- SWUpdate (Stefano Babic et al.)
- OSTree (Colin Walters et al. / Red Hat)
- Rugix Ctrl (Silitics)
While there are other approaches, such as Ubuntu Core's Snap-based updates, Balena's vertically-integrated container-based OS, or Foundries.io's aktualizr-lite, those are bound to their own specific ecosystems. In contrast, the tools we look at can all be used more or less independently without adopting a specific ecosystem.
We also limit our scope to the on-device update engine itself, i.e., the software that installs updates, verifies integrity, and manages rollback. There is a recent trend where vendors couple their update engine to a specific fleet management backend, creating a lock-in effect. Given the long lifetime of embedded devices, we believe it's important to cleanly decouple those layers. That said, we will discuss how flexibly each engine integrates with different backends, including custom distribution infrastructure.
We compare these engines along several dimensions: update strategy support, bootloader support, delta updates, security, and update delivery and backend integration.
A note on bias: We are the developers of Rugix Ctrl, so we have an obvious interest in how it compares. We have done our best to be factually accurate and fair throughout this article, but we encourage readers to verify our claims and form their own conclusions.
Background: Update Strategiesβ
Before comparing individual tools, it is helpful to establish the fundamental strategies for applying system updates on embedded Linux devices. These strategies differ in their approach to atomicity, storage requirements, and rollback capabilities.
In-Place (Single-Copy) Updatesβ
In-place updates modify the active root filesystem directly. This is the simplest strategy to implement but provides no atomicity guarantees. A power failure during an in-place update can leave the system in an inoperable state with no automatic way to recover.
In-place updates are generally not recommended for production embedded devices unless combined with additional safety mechanisms. Package-manager-based updates (e.g., using apt or dnf) are conceptually in-place updates and suffer from the same problems: a failed or interrupted update can leave the system in an inconsistent state, and there is no built-in mechanism for atomic rollback. This is particularly critical for kernel updates, where a bad update can render the device unbootable with no automatic recovery path.
A/B (Dual-Copy) Updatesβ
The most widely adopted strategy for robust system updates is the A/B scheme. The device maintains two copies of its root filesystem on separate partitions (or slots). At any point, one slot is active (the running system) and the other is inactive. An update is written to the inactive slot while the active system continues to run. After installation, the bootloader is instructed to boot from the newly written slot. If the new system fails to boot or does not pass a health check, the bootloader automatically falls back to the previous slot.
A/B updates provide strong atomicity guarantees: since the update is written to a separate partition, the currently running system is never modified during the update process. A power loss during installation simply leaves the inactive slot in an incomplete state, and the device continues to boot from the active slot as before. This makes A/B updates the gold standard for devices that must not brick under any circumstances.
The primary trade-off is storage: A/B updates require roughly twice the space for the root filesystem. For devices with constrained storage, this can be a significant cost.
Recovery (Asymmetric) Updatesβ
An alternative to symmetric A/B updates is the recovery scheme. The device maintains a single primary root filesystem and a smaller recovery partition containing a minimal system capable of applying updates. If the primary system fails, the bootloader boots into the recovery partition, which can then reflash the primary partition.
This approach requires less storage than a full A/B setup but introduces a significant limitation: the primary system cannot be updated while it is running. Instead, the device must reboot into the recovery partition to install the update, leading to longer downtime. Furthermore, the recovery partition itself is typically not updated, which can become a maintenance liability over time.
OSTree's Approachβ
OSTree takes a fundamentally different approach. Instead of maintaining separate partitions, it uses a single filesystem with a content-addressable object store, similar in concept to Git. System deployments are represented as hardlink farms pointing into the object store. When a new deployment is prepared, OSTree creates a new set of hardlinks for the updated files while sharing unchanged files with the existing deployment. The bootloader configuration is then atomically swapped using a symlink-based mechanism (the "swapped directory pattern").
This approach avoids the storage overhead of a full A/B partition layout while still providing atomic deployments and rollback. However, it requires a writable filesystem, which comes with its own challenges. Since both deployments share the same underlying filesystem, a corruption event can affect both the current and previous deployment, unlike A/B schemes where each slot is an independent block device. A writable filesystem also precludes the use of dm-verity for runtime integrity verification.
The Toolsβ
With these strategies in mind, let us briefly introduce each tool before diving into the detailed comparison.
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| Language | C++ | C | C | C | Rust |
| License | Apache-2.0 | LGPL-2.1 | GPL-2.0 | LGPL-2.0+ | MIT/Apache-2.0 |
| Standalone Focus | No | Yes | Yes | Yes | Yes |
| Since | 2016 | 2015 | 2013 | 2011 | 2023 |
Menderβ
Mender was created by Northern.tech and first released in 2016. It was designed as a complete OTA update platform with a server component for fleet management and an on-device client for applying updates. The client implements A/B rootfs updates via a well-defined state machine and can be extended through Update Modules for custom update types (e.g., containers, configuration files, or individual packages). While standalone mode exists, Mender's architecture reflects its origins as a full-stack platform. The Mender client was originally written in Go but has been rewritten in C++ to enable support for RTOS platforms. It is licensed under Apache-2.0, however, some important features are reserved for commercial tiers and not available under Apache-2.0.
RAUCβ
RAUC (Robust Auto-Update Controller) was created by Pengutronix, a German embedded Linux consulting company, with the first commit on April 22, 2015. It has become one of the most widely deployed open-source update solutions, notably powering the updates of Valve's Steam Deck (via SteamOS 3.0). RAUC is a lightweight daemon (~512 KiB binary) that manages the installation of update bundles to declaratively configured slots. Its slot concept is flexible: slots can have parent-child relationships, allowing a single update bundle to update multiple related partitions as a unit. RAUC uses SquashFS-based update bundles signed with CMS, and since version 1.5 supports a verity bundle format with dm-verity hash trees for streaming installation and a crypt format for encrypted bundles. It is written in C and licensed under LGPL-2.1.
SWUpdateβ
SWUpdate was created by Stefano Babic and has been under active development since 2013. It considers itself a framework rather than a turnkey solution. Where tools like Mender and RAUC are opinionated about how updates should work, SWUpdate provides a pipeline architecture where an incoming update stream (an SWU file, essentially a CPIO archive) is processed by a series of handlers. This gives SWUpdate exceptional flexibility, virtually any update workflow can be implemented, but also means that more engineering effort is required for the initial setup. SWUpdate includes built-in handlers for common targets and supports custom handlers written in C or Lua. It integrates with Eclipse hawkBit for fleet management via its built-in Suricatta daemon. SWUpdate is written in C and licensed under GPL-2.0.
OSTreeβ
OSTree (libostree) was initiated by Colin Walters in 2011 and has its roots in the GNOME project at Red Hat. Unlike the other tools, OSTree is not an update engine in the traditional sense but a versioning and deployment system for complete filesystem trees, often described as "Git for operating system binaries." It maintains a content-addressable object store on the device, and deployments are represented as hardlink farms pointing into the store. OSTree has a rich ecosystem: it powers Fedora Silverblue, Fedora CoreOS, Endless OS, and Torizon OS (by Toradex). The bootc project extends OSTree with OCI container-based workflows and is positioned as the future direction for the technology. It is written in C and licensed under LGPL-2.0+.
Rugix Ctrlβ
Rugix Ctrl is the update engine of the Rugix project, developed by Silitics. First introduced in July 2023 under the name Rugpi, it initially targeted Raspberry Pi devices and has since evolved into a general-purpose update engine, reaching version 1.0 in February 2026. While it is the youngest tool in this comparison, it has already found adoption at scale, powering tens of thousands of devices worldwide. Notably Umbrel, a popular self-hosting platform, has adopted it for umbrelOS. Rugix Ctrl is part of the larger Rugix ecosystem, which aims to simplify the development of embedded Linux devices. It ships as a single standalone binary with native support for delta updates and integrates with multiple fleet management backends. As part of the Rugix ecosystem, it provides integrated state management: the root filesystem is mounted read-only with an overlay for runtime writes, providing off-the-shelf factory reset and protection against configuration drift. It is written in Rust and dual-licensed under MIT and Apache-2.0.
Comparisonβ
We now turn to a structured comparison across the dimensions outlined above.
Update Strategy Supportβ
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| A/B (Symmetric) | β | β | β | β * | β |
| Recovery (Asymmetric) | β | β | β | β | β |
| Multi-Slot Configurations | β | β | β | β | β |
* OSTree achieves A/B-like behavior through its dual deployment mechanism on a single partition. It does not use separate block devices for each slot.
Mender and OSTree focus exclusively on A/B updates. Mender can be extended via Update Modules for custom update types (containers, configuration files, packages), but the rootfs update mechanism itself is limited to A/B. RAUC, SWUpdate, and Rugix Ctrl offer more flexibility, including recovery (asymmetric) schemes and extensible hook/handler systems for fully customizing the update process.
Bootloader Supportβ
To implement atomic system updates, update tools need to interface with a bootloader to effectuate the switching between versions (or the recovery system).
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| U-Boot | β | β | β | β | β |
| GRUB | β | β | β | β | β |
| systemd-boot1 | β | β | β | β | β |
| Barebox | β | β | β | β | β |
| Tryboot (RPi) | β | β |
