overlayroot vs A/B Updates: What to Pick on Embedded Linux
overlayroot (Ubuntu cloud-initramfs-tools) mounts a read-only lower root in the initramfs and stacks a writable overlay (often tmpfs) on top. A/B updates keep two (or more) rootfs slots: write the inactive slot, then let the bootloader switch and roll back. That is the dual-bank / redundant-slot model described by RAUC, Mender, and SWUpdate docs.
This post covers rootfs protection and update strategy only. Device Tree Overlay (.dtbo) load/debug is a different topic. No board anecdotes or prices—grounded in the Ubuntu overlayroot package/manpages and public A/B OTA material (RAUC basics, U-Boot A/B flow).
What are the failure modes of each?
One-line answer: overlayroot fails when changes you thought were permanent vanish after reboot, or a deliberate lower write corrupts the protected image; A/B fails when inactive-slot write, boot switch, or health confirmation breaks, leaving you on the old slot—or stuck if rollback wiring is missing.
overlayroot
- Volatile upper — With
overlayroot="tmpfs", runtime writes land on tmpfs. Reboot clears the upper; the lower root stays as imaged. That looks like “settings did not stick.” - Permanent change path — Updating the lower needs an explicit path such as
overlayroot-chroot(remount lower writable and chroot) or editing under the lower mount. Power loss mid-write can damage the very image you meant to protect. - Initramfs required — Hooks run in early userspace. Boots without initrd never apply overlayroot even if config files look correct.
- Config layers — Mixing
/etc/overlayroot.conf, overriding/etc/overlayroot.local.conf, and cmdline disable flags yields “I enabled it but still have RW/.” - Protection ≠ atomic update — Strong against accidental runtime pollution; not a built-in rollback to a previous system image after a failed OTA.
A/B
Shared points from Bootlin’s U-Boot A/B talk and RAUC basics:
- Inactive-slot write fails — Keep the active slot. The update agent reports failure; the running system should remain bootable.
- Write OK, boot fails — After switching, panics/watchdog resets/failed health checks should trip bootcount / bootlimit / altbootcmd (or RAUC
mark-good/mark-bad) and fall back. Without that chain, recovery is hard. - Bootloader environment damage — Slot pointers (
bootpart,upgrade_available, implementation-specific names) desync userspace and the bootloader. - Layout cost — Symmetric A/B roughly doubles rootfs flash. Wrong slot class mapping installs “successfully” to a non-boot path.
- Missing commit — If the new image runs but never marks good, the next reboot may treat it as failed and roll back.
| Aspect | overlayroot | A/B slots |
|---|---|---|
| Protects against | Runtime writes / accidental lower pollution | Failed system image replacement |
| Typical failure look | Changes gone after reboot / lower corrupted on bad permanent write | Stay on active slot or roll back to previous |
| Prerequisites | Initramfs + overlay config | Dual+ slots + bootloader integration |
How do they fit OTA?
One-line answer: A/B is an OTA slot-switch model; overlayroot is a runtime root-protection layer, not an update framework. Treating them as the same “update style” muddies the choice.
overlayroot and OTA
- Field
apt upgradeinto a tmpfs upper disappears on reboot. - Real image refresh means changing the lower (offline reflash, work inside
overlayroot-chroot, factory redeploy)—paths that do not give you dual-slot atomic rollback by default. - Poor primary strategy when the product must remotely replace the root and recover on failure. Better for kiosks/demos where the root rarely changes and runtime state is disposable.
A/B and OTA
Common public-doc flow:
- Write/verify a signed bundle to the inactive slot
- Point the bootloader at that slot for the next boot
- Reboot, health-check → commit (
mark-good) or fall back - Optional deltas, streaming, artifact repos per framework
RAUC ties slot classes, groups, and boot confirmation to system.conf; Mender/SWUpdate similarly assume dual rootfs plus U-Boot (or equivalent) variables. If you need signed fleet OTA with interrupt recovery, A/B (or equivalent redundant slots) matches the tooling.
Using both?
Products may ship read-only slot contents plus a temporary overlay for runtime, but which slot is active and how failed updates revert still belongs to A/B (or equivalent). Do not expect overlayroot alone to replace rollback.
What about development images?
One-line answer: Dev/experimental images usually keep a writable single root (or disable overlayroot); production images enable overlayroot protection and/or A/B slots according to update policy.
Selection notes aligned with documented roles:
- Need persistent packages, debug artifacts, logs on disk — tmpfs upper wipes on reboot. Use cmdline
overlayroot=disabledor empty config for a normal RW root while developing. - Reproduce field protection — Enable
overlayroot="tmpfs"on a staging image and practice permanent edits viaoverlayroot-chroot. Frequent lower edits with overlay enabled are costly. - Validate OTA — Even on a lab board you need two slots + bootloader vars + mark-good/bad. A single-partition dev image cannot exercise rollback/bootcount failure modes.
- Tight flash on prototypes — Symmetric A/B costs space; many teams ship features on one root first, then add slots for production. (Asymmetric/rescue layouts are documented separately by RAUC and others.)
- One-line picker
- “Don’t let runtime trash the root” → overlayroot (or equivalent RO root + overlay)
- “Replace the system remotely and fall back on failure” → A/B OTA
- “Both” → atomic slot updates, optionally with runtime RO/overlay. Unrelated to Device Tree Overlay debug.
Wrap-up
overlayroot keeps a RO lower and a writable upper so runtime pollution is cheap to discard. A/B uses redundant slots plus bootloader health so failed system OTAs can return to the previous image. Write down failure modes, OTA needs, and whether the image must stay writable for development—then choose—without conflating this with Device Tree Overlay work.