If you are running one of the standard variants of Fedora Linux, such as Fedora Workstation or one of the other non-ostree variants, you might have used the dnf swap command at some point to replace one package with another one. This article will describe a technique for performing a similar operation on an ostree installation using the rpm-ostree command.

The dnf swap command prevents conflicts when two packages contain files with the same name and filesystem path. It is necessary when other system packages depend on a package that you want to replace (“swap out”) with an alternative version, but completely uninstalling the dependent packages and then reinstalling everything with the alternative isn’t practical.

However, that doesn’t work very well with Fedora Silverblue and the ostree variants. They do not have a rpm-ostree swap command. Luckly, there is a way to achieve similar functionality. We just need to uninstall the old package and install the new package in the same transaction!

Use rpm-ostree to replace packages in the base image

The most common scenario, especially when not overlaying many packages or none at all, is to replace packages in the base image.

A good example of this is replacing nano-default-editor, which was made the default in Fedora Linux 33, with vim-default-editor. Some users would prefer using vim, but dnf swap nano-default-editor vim-default-editor won’t work on ostree-based systems.

If using dnf, when trying to install vim-default-editor, you will most likely hit dependency conflicts and the transaction will fail. The output below is what you would get and it effectively means that both nano-default-editor and vim-default-editor provide system-default-editor, but only one provider of system-default-editor can be installed at once. (vim-default-editor or nano-default-editor can be installed, but both cannot be installed at the same time.)

$ sudo dnf install vim-default-editor
...
Error: 
 Problem: problem with installed package nano-default-editor-7.2-4.fc39.noarch
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora
  - package vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from fedora conflicts with system-default-editor provided by vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora
  - package vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from fedora
  - conflicting requests
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.1.016-1.fc39.noarch from updates
  - package vim-default-editor-2:9.1.016-1.fc39.noarch from updates conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from fedora conflicts with system-default-editor provided by vim-default-editor-2:9.1.016-1.fc39.noarch from updates
  - package vim-default-editor-2:9.1.016-1.fc39.noarch from updates conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from fedora
(try to add '--allowerasing' to command line to replace conflicting packages or '--skip-broken' to skip uninstallable packages)

If you attempt the same on rpm-ostree, a similar error message appears, effectively having the same meaning.

$ rpm-ostree install vim-default-editor
...
Resolving dependencies... done
error: Could not depsolve transaction; 1 problem detected:
 Problem: conflicting requests
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.1.016-1.fc39.noarch from updates
  - package vim-default-editor-2:9.1.016-1.fc39.noarch from updates conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora
  - package vim-default-editor-2:9.0.1927-1.fc39.noarch from fedora conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2048-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2048-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2081-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2081-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2105-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2105-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2120-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2120-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2153-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2153-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2167-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2167-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.0.2190-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.0.2190-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System
  - package nano-default-editor-7.2-4.fc39.noarch from @System conflicts with system-default-editor provided by vim-default-editor-2:9.1.016-1.fc39.noarch from updates-archive
  - package vim-default-editor-2:9.1.016-1.fc39.noarch from updates-archive conflicts with system-default-editor provided by nano-default-editor-7.2-4.fc39.noarch from @System

So, for this to work, we have to look into removing nano-default-editor first. In this scenario we have to look into rpm-ostree override remove, which allows us to remove packages from the base image. But, if we simply try to remove nano-default-editor, it will fail saying default-editor needs a package that provides system-default-editor. In other words, if we want to remove nano-default-editor we need to install vim-default-editor or another package that provides system-default-editor. Another possibility is removing default-editor completely and losing this functionality:

$ rpm-ostree override remove nano-default-editor
...
Resolving dependencies... done
error: Could not depsolve transaction; 1 problem detected:
 Problem: package default-editor-7.2-4.fc39.noarch from @System requires system-default-editor, but none of the providers can be installed
  - conflicting requests

Thankfully, the rpm-ostree override remove command accepts an extra ‐‐install argument which allows us to also install a package along with the removal! So, if we add vim-default-editor as well, we get:

$ rpm-ostree override remove nano-default-editor --install vim-default-editor
<snip>
Resolving dependencies... done
Will download: 6 packages (10,0 MB)
Downloading from 'fedora'... done
Downloading from 'updates'... done
Importing packages... done
Applying 1 override and 6 overlays
Processing packages... done
Running pre scripts... done
Running post scripts... done
Running posttrans scripts... done
Writing rpmdb... done
Writing OSTree commit... done
Staging deployment... done
Freed: 213,9 MB (pkgcache branches: 0)
Removed:
  nano-default-editor-7.2-4.fc39.noarch
Added:
  gpm-libs-1.20.7-44.fc39.x86_64
  vim-common-2:9.0.2190-1.fc39.x86_64
  vim-default-editor-2:9.0.2190-1.fc39.noarch
  vim-enhanced-2:9.0.2190-1.fc39.x86_64
  vim-filesystem-2:9.0.2190-1.fc39.noarch
  xxd-2:9.0.2190-1.fc39.x86_64
Use "rpm-ostree override reset" to undo overrides
Run "systemctl reboot" to start a reboot

And now, after a reboot, vim-default-editor should be installed and vim should be the default editor. You can confirm the results with rpm-ostree status:

$ rpm-ostree status
State: idle
Deployments:
● fedora:fedora/39/x86_64/silverblue
                  Version: 39.20240106.0 (2024-01-06T01:35:56Z)
               BaseCommit: 2d052ca5e08b07406612e68cbb4ec67e86d733dba5e458234ad65bc5a4ad5b51
             GPGSignature: Valid signature by E8F23996F23218640CB44CBE75CF5AC418B8E74C
      RemovedBasePackages: nano-default-editor 7.2-4.fc39
          LayeredPackages: vim-default-editor

The command to undo such transaction would be rpm-ostree override reset nano-default-editor ‐‐uninstall vim-default-editor.

Replacing overlaid packages

When replacing overlaid packages the process is considerably simpler. There are three commands to consider: rpm-ostree install, rpm-ostree uninstall and rpm-ostree upgrade.

rpm-ostree install receives a list of packages to be installed, but also supports a ‐‐uninstall parameter to remove packages in the same transaction. rpm-ostree uninstall receives a list of packages to be uninstalled, but also supports a ‐‐install parameter to install packages in the same transaction.

rpm-ostree upgrade upgrades the system, but also supports the ‐‐install and ‐‐uninstall parameters to install or uninstall packages in the same transaction.

Ultimately, for overlaid packages, it’s mostly a choice of whether to also update the system and then choosing the most convenient command.

Conclusion

While, due to the nature of rpm-ostree, it may not seem that dnf swap-like functionality is achievable, a closer look at its commands shows similar flexibility, even if in different clothing.