You ran dnf and the terminal said no
You installed Fedora Silverblue six months ago. You ran sudo dnf upgrade out of habit, and the terminal told you the command is disabled. Or you tried to install a kernel module and got a read-only filesystem error. You remember reading that Silverblue is "immutable," but the upgrade process feels like magic. You need to move from Fedora 40 to 41, or just get the latest security patches, and you want to do it without breaking the system or losing your layers.
Silverblue does not use dnf for system updates. The base image is read-only. Modifying it in place would break the atomic guarantee. Instead, rpm-ostree manages the OS as a single versioned image. You stage changes, reboot, and the system boots into the new image. If anything goes wrong, you roll back to the previous image. The running system is never partially updated.
How rpm-ostree keeps the system safe
Traditional Fedora Workstation updates files one by one. If power fails during the update, the system can be left in a half-updated state with mismatched libraries. Silverblue treats the operating system as a bootable image. Think of the OS as a USB stick. When you upgrade, rpm-ostree downloads a new image and writes it to a separate slot on the disk. The reboot switches the boot loader to point at the new slot. The old slot stays untouched.
This is atomic. Either the whole new image boots, or it doesn't. There is no middle ground. The bootloader sees two deployments. You can switch between them instantly. Your user data in /home and your configuration in /etc persist across deployments. The base image is immutable, but your layers and config survive every reboot.
Trust the image. File-by-file updates drift. Image updates stay consistent.
Stage updates and reboot
Here's how to check for updates and stage them for the next boot. This applies to patch updates within the same Fedora release.
# Check current deployment and pending transactions
rpm-ostree status
# WHY: Shows the current boot ID, the version, and any layers or deployments waiting.
# The "Deployments" section lists what is currently running versus what is staged.
# Look for the "State" line. "Idle" means no transaction is in progress.
# Download and stage the latest updates for the current release
sudo rpm-ostree upgrade
# WHY: Fetches the new OS image from the configured repository and stages it as a new deployment.
# This does not modify the running system. The changes apply only after a reboot.
# The command downloads the delta if available, saving bandwidth.
Once the download completes, you must reboot for the new image to become active. The system will boot into the new version, but you can still revert to the previous boot if something goes wrong.
# Reboot to activate the staged deployment
sudo reboot
# WHY: Switches the boot loader to the new deployment. The old deployment remains available for rollback.
# The bootloader menu will show both versions for a short time.
Reboot before you debug. The new image is staged, but it isn't active until the system restarts.
Move to a new major release
Moving between major releases requires a rebase, not an upgrade. This switches the underlying image reference. A rebase downloads the new base image and migrates your layers and /etc configuration automatically. This is distinct from a standard patch update.
# List available releases to find the target ref
rpm-ostree origin
# WHY: Displays the current origin configuration, including the repository and ref used for the base image.
# This helps you verify the syntax before rebasing.
# The ref format is usually ostree://fedora/fedora-x86_64/silverblue:VERSION.
# Rebase to Fedora 41 Silverblue
sudo rpm-ostree rebase ostree://fedora/fedora-x86_64/silverblue:41
# WHY: Downloads the Fedora 41 base image and stages it as the new deployment.
# Your layered packages and /etc configuration are preserved and migrated automatically.
# If a layered package is incompatible, the command will warn you before proceeding.
After the rebase completes, reboot to switch to the new major release. Verify the version immediately after boot.
# Reboot to activate the new major release
sudo reboot
# WHY: Boots into the Fedora 41 image. The bootloader will prefer this deployment.
# The Fedora 40 deployment remains available for rollback if needed.
Snapshot your important data before a major rebase. The migration is safe, but verify your backups exist.
Install packages on an immutable host
If you need a package that isn't in the base image, use rpm-ostree install. This layers the package on top of the immutable base. The layer is transactional. If the layer breaks the system, you can roll back. Do not use dnf on the host. dnf cannot modify the base image and will fail.
# Install a package on the host system
sudo rpm-ostree install vim
# WHY: Adds vim to the layer tree and stages a new deployment with the package included.
# The package is available after reboot. The base image remains unchanged.
# Layers are merged into the root filesystem at boot time.
# Reboot to apply the layer
sudo reboot
# WHY: Activates the deployment with the new layer.
# The package is now available in the running system.
Convention aside: rpm-ostree install is for host packages. Use toolbox or distrobox for development environments where you need a mutable filesystem and full dnf access. The host stays clean. The containers handle the chaos.
Verify the deployment
Confirm the system booted into the expected version and your layers are intact. This step catches silent failures where the bootloader might have stuck to the old deployment.
# Verify the active deployment and version
rpm-ostree status
# WHY: Confirms the "Deployments" section shows the new version as the current boot.
# Check the "Layered packages" list to ensure your custom installs survived the upgrade.
# The "Pinned packages" list shows packages that are locked to specific versions.
Run rpm-ostree status first. Read the deployment list before assuming the upgrade stuck.
Common errors and recovery
You will encounter errors. The system is designed to handle them. If you see Error: Transaction test error: package ... conflicts with ..., the conflict is usually a layered package that clashes with the base image. Remove the conflicting layer or update it. If you see [FAILED] Failed to start NetworkManager.service during boot, your network configuration probably references a missing interface name. Check /etc/NetworkManager/ for stale configs.
SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. Most denials are caused by custom scripts or misconfigured services. Fix the policy or the script. Disabling SELinux hides the problem.
If the new version fails to boot or breaks a critical service, roll back immediately. The rollback is safe and preserves your current state.
# Roll back to the previous deployment
sudo rpm-ostree rollback
# WHY: Sets the boot loader to prefer the previous deployment on the next reboot.
# This is safe and preserves your current state.
# The command updates the bootloader configuration to point to the old image.
# Reboot to apply the rollback
sudo reboot
# WHY: Restarts the system into the previous image.
# Your data and config are intact. The broken deployment remains available for debugging.
If the boot menu is gone, GRUB rescue is your friend, not your enemy. Use the rollback command from a live environment if needed.
Manage disk space and old deployments
rpm-ostree keeps old deployments to enable rollback. Over time, this consumes disk space. If you run low on space, clean up old deployments. Keep at least two deployments to maintain rollback capability.
# Remove old deployments to free disk space
sudo rpm-ostree cleanup --deployments
# WHY: Deletes deployments that are no longer needed, reclaiming disk space.
# Keep at least two deployments to maintain rollback capability.
# The command removes deployments older than the current and previous boot.
# Check disk usage after cleanup
df -h /
# WHY: Verifies that disk space has been reclaimed.
# The root filesystem should show increased available space.
Convention aside: rpm-ostree cleanup is the normal maintenance command. Run it monthly if you upgrade frequently. The cache also grows. Use sudo rpm-ostree cleanup --cache to remove downloaded deltas if space is tight.
Edit /etc. Never edit /usr/lib. Config files in /etc/ are user-modified and persist across upgrades. Files in /usr/lib/ ship with the package and are overwritten on every update. Your changes in /usr/lib/ will vanish.
Choose the right tool for the job
Use rpm-ostree upgrade when you want security patches and bug fixes within the current Fedora release.
Use rpm-ostree rebase when you are moving to a new major release like Fedora 41 to 42.
Use rpm-ostree install when you need a package on the host system that is not in the base image.
Use toolbox or distrobox when you need a mutable environment for development or building software.
Use rpm-ostree rollback when the new deployment fails to boot or breaks a critical service.
Use rpm-ostree cleanup when disk space is low and you want to remove old deployments.
Stay on the current release until the next Fedora version ships if you only need stability and not new features.