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 | β | β | β | β | β |
| Barebox | β | β | β | β | β |
| Tryboot (RPi) | β | β | β | β | β |
| UAPI (BLS) | β | β | β | β | β |
| EFI | β | β | β | β | β |
| Custom | β | β | β | β | β |
RAUC has the broadest built-in bootloader support, including Barebox (which is maintained by the same company, Pengutronix) and EFI. Rugix Ctrl is the only tool supporting Raspberry Pi's Tryboot mechanism, which is the official way to implement A/B updates on Raspberry Pi hardware. OSTree is the only tool with built-in support for the UAPI Boot Loader Specification. RAUC and Rugix Ctrl support custom bootloader integrations, as does SWUpdate through its handler system. This allows them to be adapted to any bootloader through custom integrations.
RAUC and Mender both implement their own ways of interfacing with GRUB and U-Boot to effectuate atomic switching and rollback. Notably, Rugix Ctrl is the only tool that provides bootloader integration compatible with other tools. It provides both Mender and RAUC-compatible boot flows that enable (a) the usage of existing board integrations of the other tools and (b) safe migrations in the field without reflashing.
Delta Updatesβ
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| Dynamic (Block-Based) | β | β | β * | β | β |
| Dynamic (File-Based) | β | β | β | β | β |
| Static (Delta Compression) | βοΈ** | β | β * | β | β |
| Content-Defined Chunking | β | β * | β * | β | β |
* Requires integration with external tools (Zchunk, Casync, rdiff).
** Only available in commercial versions.
Delta updates are critical for bandwidth-constrained deployments and devices on metered connections. We published a comprehensive study of different delta update techniques with reproducible benchmarks in an earlier article. We refer to this article for an in-depth comparison and only provide a summary here.
- Mender supports delta compression via Xdelta but only in its commercial tiers, making it unavailable for open-source users.
- RAUC provides native block-based diffing through its adaptive update mechanism using a fixed block size of 4 KiB. Content-defined chunking is available through Casync integration but requires an external tool and setup effort.
- SWUpdate does not natively implement delta updates but can integrate with external tools like Zchunk and rdiff. This requires additional setup effort.
- OSTree supports file-level diffing natively for dynamic pulls and pre-computed static deltas for offline scenarios. Its file-level granularity avoids the "noise" inherent in block-level diffing of filesystem images, where minor changes to file metadata or layout can cause large portions of the image to differ at the block level.
- Rugix Ctrl is the only tool that natively supports both dynamic block-based diffing with content-defined chunking and static delta compression (via Xdelta). Content-defined chunking is particularly valuable because it handles insertions and layout shifts more gracefully than fixed-size block diffing, producing smaller deltas across a wider range of update scenarios.
As our benchmarks on two years of real updates according to different cadences have shown, Rugix Ctrl's delta update support is best-in-class across the board.1 Its dynamic delta updates outperform RAUC's adaptive updates due to the use of content-defined chunking and the low overhead as the same block index is used for cryptographic verification and delta updates. RAUC via Casync and SWUpdate via Casync or Zchunk can provide similar results as Rugix Ctrl for dynamic delta updates but require additional integration work.
Generally, static delta updates using delta compression can be up to twice as efficient as the dynamic techniques. Rugix Ctrl is the only open-source tool supporting them natively for traditional partition-based updates. RAUC doesn't support them and SWUpdate requires a manual integration with Xdelta. According to our benchmarks, static delta updates using delta compression also outperform file-based updates on frequent minor updates.
On infrequent major updates, delta updates generally lose their advantages and even lead to overhead compared to just compressing the entire update. In those scenarios, file-based delta updates have shown to be most effective, as they can simply compress the new files in their entirety. Those updates are, however, infrequent.
Securityβ
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| Bundle/Artifact Signing | β | β | β | β | β |
| Block-Wise Verification | β | β | β | β | β |
| Encrypted Updates | β | β | β | β | β |
| Secure by Default | β | β | β | β | β |
| Memory-Safe Language | β | β | β | β | β |
Security is an important dimension for an update engine. The update mechanism is the path through which new code reaches the device; a vulnerability here can compromise the entire fleet. All tools support signing of update artifacts in some form. However, there are important differences in the depth of security features:
-
Block-wise verification (checking individual blocks before writing them) is supported by RAUC (via dm-verity over the verity bundle format), OSTree (via its content-addressable store), and Rugix Ctrl (via a Merkle tree embedded into its bundle format). This prevents partial writes of corrupted data, which is a stronger guarantee than whole-artifact verification alone.
-
Encrypted updates are supported by RAUC (via its
cryptbundle format) and SWUpdate (with per-device asymmetric key wrapping). Both use a similar approach: the payload is symmetrically encrypted with AES, and the AES key is wrapped with per-device asymmetric keys. This allows individual devices to be excluded from future updates if their keys are compromised, providing a form of device revocation. Encrypted updates are relevant when firmware contains trade secrets that must be protected even if the update file is intercepted or extracted from the device.2 Neither Mender, OSTree, nor Rugix Ctrl currently offer encrypted updates. -
Secure by default refers to whether the tool requires update verification out of the box, without explicit opt-in by the user. RAUC enforces signature verification unconditionally: there is no
--no-verifyflag forrauc install, and if no keyring is configured, installation fails rather than falling back to unverified mode. Rugix Ctrl requires bundle verification by default as of version 1.0: either a valid signature or a known bundle hash must be present, and unverified updates must be explicitly opted into. The remaining tools allow unverified updates unless explicitly configured otherwise, a default that, while convenient during development, creates risk if it carries over into production. -
Memory safety is an increasingly important consideration for security-critical software. The U.S. Cybersecurity and Infrastructure Security Agency (CISA), the NSA, and other agencies have recommended the adoption of memory-safe languages for new security-sensitive projects. The established C-based tools have years of hardening, fuzzing, and CVE response behind them, and their track records speak for themselves. That said, memory safety eliminates entire vulnerability classes (buffer overflows, use-after-free, out-of-bounds reads) at the language level, rather than relying on catching them after the fact. Among the tools considered, only Rugix Ctrl is written in a memory-safe language (Rust). For a component that runs with root privileges and parses untrusted binary input, this distinction matters.
Currently, no single tool covers all of these properties. Rugix Ctrl is the only memory-safe implementation and one of two (alongside RAUC) that enforce verification by default. RAUC and SWUpdate are the only two that support encrypted updates. Teams should weigh which properties matter most for their threat model.
Update Delivery and Backend Integrationβ
Once an update is built, it needs to reach the device.
| Mender | RAUC | SWUpdate | OSTree | Rugix Ctrl | |
|---|---|---|---|---|---|
| Self-Contained Updates | β | β | β | β | β |
| Streaming from HTTP | β | β | β | β | β |
| Streaming from Stdin | β | β | β | β | β |
Self-contained updates. Mender artifacts, RAUC bundles, SWUpdate's SWU files, and Rugix bundles are all single files that can be served from any HTTP server, CDN, object store, or even delivered via USB. This makes distribution infrastructure simple. OSTree is fundamentally different: it uses a content-addressable object store where each file and directory tree is a separate object fetched individually over HTTP, requiring either an OSTree-specific repository server or pre-computed static deltas.
An important caveat applies to delta updates. RAUC's Casync integration requires a separate chunk store (a .castr directory) alongside the bundle as the bundle itself contains only index files, not the actual data. Similarly, SWUpdate's Zchunk and Casync integrations require additional server-side infrastructure beyond the SWU file. In contrast, RAUC's native adaptive updates and Rugix Ctrl's dynamic delta updates work with a single file using HTTP range requests to fetch only what is needed. This keeps distribution infrastructure simple even for bandwidth-efficient updates.
Streaming. Streaming allows the device to write update data directly to the target as it is being downloaded, without first storing the entire update locally. This is important for devices with limited storage. SWUpdate pioneered this approach with its zero-copy pipeline architecture, where the update stream is processed and written to the target in a single pass. Rugix Ctrl follows a similar architecture and, like SWUpdate, supports custom handlers that can process arbitrary payloads within the stream. As a result, both tools support streaming from arbitrary sources (e.g., stdin, named pipes), which makes it easy to integrate with custom delivery mechanisms. For instance, a web UI where an update is uploaded and directly streamed to disk is straightforward to implement.
RAUC and OSTree only support streaming from HTTP, where range queries (RAUC) and individual file fetching (OSTree) provide the random access these tools require.
Fleet management integration. An update engine on its own only installs updates; it does not decide when or which update to install. That is the job of a fleet management backend. All tools can be triggered via a standalone CLI, making it straightforward for any external process (whether a fleet management agent, a cron job, or a custom script) to initiate an update. Beyond the CLI, RAUC and Mender expose a D-Bus API for tighter programmatic integration with system services. SWUpdate offers IPC and REST interfaces for the same purpose. Rugix Ctrl currently relies on its CLI interface.
It is worth noting that some of Mender's features, including delta updates, are only available when used with Mender's server as part of a commercial subscription. This means that teams using Mender in standalone mode or with a third-party backend do not have access to the full feature set.
Discussionβ
The comparison above covers what each tool can do today. In this section, we highlight each tool's core strength, address cross-cutting themes like state management and build system integration, and offer guidance on choosing the right tool.
The Core Strengths of Each Toolβ
SWUpdate pioneered the streaming handler pipeline for embedded Linux updates and has the longest track record with this approach. Its support for custom handlers in both C and Lua lowers the barrier for teams that need to implement non-standard update workflows.
RAUC has a decade of production history, including powering updates on the Steam Deck. It enforces signature verification unconditionally, with no way to bypass it at install time. Among the tools compared here, RAUC has the widest storage backend support, including NAND, NOR, UBI volumes, UBIFS, and eMMC hardware boot partitions, making it the strongest choice for devices with non-standard flash storage. It is also one of only two tools (alongside SWUpdate) that supports encrypted updates with per-device key wrapping.
OSTree is fundamentally different from the other tools. Its hardlink-based deployments avoid the storage overhead of A/B partitions, and it has a large ecosystem, primarily in the desktop and server space (Fedora Silverblue, Fedora CoreOS, Endless OS). For embedded Linux, adoption is narrower, with Torizon OS being the most prominent example.
Mender offers the most integrated out-of-the-box experience for teams that want fleet management and device updates in a single commercial platform with a partially open-source core. The trade-off is tighter coupling to Mender's server and commercial tiers that gate features like delta updates.
Rugix Ctrl is a modern take that draws on the best practices of the established tools: a streaming handler architecture like SWUpdate, dynamic delta updates with HTTP range requests like RAUC, best-in-class delta update efficiency through native content-defined chunking and delta compression, and a security posture built on a memory-safe language (Rust) with secure-by-default update verification.
