Why Fedora Atomic Desktops Changed How I Think About OS Updates
Fedora Atomic Desktops replace in-place updates with immutable OSTree images. Every upgrade creates a bootable deployment you can roll back from the GRUB menu in seconds. Here's how the model works, where your data lives, why layered packages are a trap, and what breaks when /usr goes read-only.
07 Jun 2026, 13:30 UTC

The Problem: Updates That Break Things at the Worst Time
You're halfway through a deploy, a kernel update lands, and suddenly your Wi-Fi module won't load. Or a library upgrade pulls in a conflicting dependency that breaks your build toolchain. Traditional mutable systems like Fedora Workstation apply changes in-place — there's no "undo" button except restoring from backup or fighting dnf history undo through a half-broken state.
Fedora Atomic Desktops (Silverblue, Kinoite, Sericea, Onyx) solve this differently: the OS is an immutable OSTree image. Every update produces a new, complete bootable deployment. The previous one stays intact in the bootloader. Rollback is a GRUB menu selection away — seconds, not hours.
How the Image Model Works
rpm-ostree composes the base OS as a read-only filesystem tree (mounted at /usr). Each rpm-ostree upgrade pulls a new commit from the Fedora remote (e.g., fedora/41/x86_64/silverblue), stages it as a new deployment, and adds a Boot Loader Specification entry. On reboot, the new deployment becomes active. The old one remains, marked pinned: 0 until you explicitly unpin or it ages out.
Run rpm-ostree status on any Atomic Desktop to see this in action:
$ rpm-ostree status
State: idle
Deployments:
● fedora:fedora/41/x86_64/silverblue
Version: 41.20241110.0 (2024-11-10T14:32:00Z)
BaseCommit: a1b2c3d4e5f6...
GPGSignature: Valid signature by Fedora 41
LayeredPackages: none
Local: no
Pinned: 1
fedora:fedora/41/x86_64/silverblue
Version: 41.20241103.0 (2024-11-03T12:15:00Z)
BaseCommit: 9f8e7d6c5b4a...
GPGSignature: Valid signature by Fedora 41
LayeredPackages: none
Local: no
Pinned: 0
The ● marks the booted deployment. Pinned: 1 means it won't be garbage-collected. Two deployments = instant rollback capability.
Where Your Data Lives: /var and /etc
Immutability doesn't mean everything is frozen. /var is a separate writable partition (or bind mount) that persists across deployments — logs, databases, container storage, user homes all survive upgrades untouched.
/etc is special: it's managed by a three-way merge on each upgrade. Your local changes are preserved while upstream updates are applied. If a config file you edited also changed upstream, rpm-ostree creates .rpmnew (new upstream version) and .rpmsave (your old version) alongside the merged result. You resolve conflicts manually — no silent overwrites.
Try it: edit /etc/ssh/sshd_config, then run rpm-ostree upgrade --check (dry-run) and watch for merge notes. The actual upgrade will show merging /etc/ssh/sshd_config in the transaction output.
Layered Packages: Powerful but Costly
Need an RPM not in the base image? rpm-ostree install htop layers it on top. The package is unpacked into the new deployment at build time, so it persists across rebases. But each layer adds 50–200 MB, increases attack surface, and can cause dependency conflicts with the base image on future upgrades.
Real example: layering akmod-nvidia for proprietary drivers. Every kernel update triggers a full image rebuild (the akmod compiles the kernel module into the new deployment). That's 2–5 minutes of CPU time per upgrade. Worse, Secure Boot enrollment must be managed manually via mokutil — the MOK key isn't part of the image.
Better path for user apps: Flatpaks (sandboxed, portal-mediated) or toolbox/distrobox containers (mutable dnf environments for dev tooling, build chains, legacy apps). Reserve layering for system-level things: kernel modules, SELinux policy modules, early-boot utilities.
A Worked Rollback Scenario
Say a kernel update breaks your Wi-Fi (common with proprietary drivers). You're at the GRUB menu on reboot:
- Select the previous deployment entry (labeled by version/timestamp).
- System boots into the known-good state — kernel, initramfs, userspace all reverted.
- Verify:
rpm-ostree statusnow shows the rolled-back deployment withPinned: 1. - Optional: make it permanent with
rpm-ostree rollback(marks current as pinned, previous as default).
No live USB, no chroot, no dnf history archaeology. The entire OS state — including the broken kernel module — is gone.
Trade-offs You'll Hit
- /usr immutability breaks installers that write to
/usr/local/binor/usr/lib. Migrate scripts to~/.local/bin,/opt, or container volumes. This catches manycurl | shinstallers off guard. - Major version rebases (40 → 41) are manual:
rpm-ostree rebase fedora:fedora/41/x86_64/silverblue. Test in a VM first —/etcmerge conflicts can leave the system unbootable if unresolved. - Flatpak portal restrictions block filesystem access for IDEs, debuggers, game launchers.
flatpak override --filesystem=hostworks but defeats sandboxing; prefer portal APIs (e.g.,xdg-desktop-portalfile chooser). - SELinux policy changes require building a custom image via
rpm-ostree composeor the newerbootc(Bootable Container) workflow — not possible via runtime layering.
What to Do Next
If you're on Fedora Workstation and curious, spin up a VM with the Silverblue or Kinoite ISO. Run rpm-ostree status, trigger an upgrade, test a rollback. Layer one package (rpm-ostree install vim), then remove it (rpm-ostree uninstall vim) and watch the deployment count drop. Create a toolbox container (toolbox create --release f41) and install build tools there instead of layering.
For new projects, evaluate bootc (Containerfile-based image builds) — it's the designated successor to rpm-ostree compose and aligns with standard container tooling. The rpm-ostree compose path is in maintenance mode.
The mental shift: stop thinking of the OS as a mutable pile of packages you tweak. Start treating it as a versioned artifact you rebase — like a container image, but for your laptop.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.