openSUSE:Packaging for transactional-updates
- Build Service cross distribution howto
- Build Service Tips and Tricks
- Build Service Tutorial
- Creating a changes file (RPM)
- Firewalld/RPM Packaging
- Java jpackage-utils
- Java RPM Macros
- Mvyskocil/Shared library packaging policy
- Package dependencies
- Package description guidelines
- Package group guidelines
- Package maintainership guide
- Package naming guidelines
- Package security guidelines
- Package source verification
- Packaging Bazel
- Packaging Branding
- Packaging Bundler
- Packaging checks
- Packaging Conventions RPM Macros
- Packaging desktop menu categories
- Packaging Fonts
- Packaging Games
- Packaging Go
- Packaging guidelines change process
- Packaging Haskell
- Packaging init scripts
- Packaging Java
- Packaging Lisp
- Packaging Lua
- Packaging Multiple Version guidelines
- Packaging nodejs
- Packaging Patches guidelines
- Packaging Perl
- Packaging PHP
- Packaging Python
- Packaging R
- Packaging Ruby
- Packaging scriptlet snippets
- Packaging vdr
- Packaging wxWidgets
- Packaging XML Schemas and Stylesheets
- Packaging/Users And Groups
- Patches Guidelines for X11:XOrg Project
- RPM conditional builds
- Ruby Gem Strategies
- Science HPC Packaging
- Shared library packaging policy
- Specfile guidelines
- Systemd packaging guidelines
- Packaging guidelines
This document describes requirements for RPMs to work together with transactional updates.
Transactional updates are atomic. This means, either the update is fully applied without any error, or no change is made to the system. Additionally transactional upates should not influence the currently running processes. On openSUSE we achieve this by using btrfs with snapshots and rollback. But instead of creating a snapshot, updating the current system and rolling back if an error happened, we create a snapshot, update this snapshot, and do a "rollback" to that snapshot if no error occured. In this situation, not all data is available. Accessible is only the main root btrfs subvolume. All other subvolumes, which were created to prevent them from being rolled back, are not accessible during update of the RPM! This means, any file normally stored in these subvolumes cannot be accessed and modified, or new files created during update are not visible later in the running system. This includes especially the /srv, /opt and /var directories.
FHS 3.0 says about this directories:
- /opt is reserved for the installation of add-on application software packages.
- /srv contains site-specific data which is served by this system.
- /var contains variable data files. This includes spool directories and files, administrative and logging data, and transient and temporary files. It is specified here in order to make it possible to mount /usr read-only. Everything that once went into /usr that is written to during system operation (as opposed to installation and software maintenance) must be in /var.
- /var/lib holds state information pertaining to an application or the system. State information is data that programs modify while they run, and that pertains to one specific host. Users must never need to modify files in /var/lib to configure a package's operation, and the specific file hierarchy used to store the data must not be exposed to regular users.
Most of the openSUSE RPMs are fine and will not create any problems. Others need to be adjusted. Most of the changes are not only needed for transactional updates, but also for snapshots and rollback.
Data and applications
User data and applications need to be strictly separated. User data should be in another subvolume than the main root subvolume with the application. Applications should always be in the main root subvolume and not in other subvolumes. "/srv" is a real nightmare in this regard: it contains applications, user data and configuration files mixed up.
Pre/Post install sections
Applications modifying data or config files in the pre/post install sections need to be careful, where this data is located. If the data is in other subvolumes, the modifications should be done during the next reboot, e.g., with a systemd unit file. But be careful that the unit is only running once after the update and not with every reboot again.
Since the new/updated applications are not available in the running system, restarting any service does not make any sense, it will only interrupt the running services and start the old code again. The standard systemd macros take care of this and are fine.
If an RPM contains directories which are outside the root subvolume, these directories will also not be visible, same for changes of ownership or permissions. For /var and /srv we have a tool which reads the RPM database at boot time and creates missing directories. systemd-tmpfiles can be used to create new directories, for example, too.
Files in /var
RPMs should not package files in /var, as these files cannot be created, updated or deleted during installation, update or removal of that package. A better solution is to use systemd-tmpfiles to create these files:
- Store the files in a directory below /usr/share or /usr/lib
- Create a /usr/lib/tmpfiles.d/<package>.conf file which copies or links the file to /var
An example (taken from ypserv) could look like:
d /var/yp 0755 - - - L /var/yp/Makefile - - - - ../../usr/lib/yp/ypMakefile L /var/yp/securenets - - - - ../../usr/lib/yp/securenets.example
%post %tmpfiles_create ypserv.conf
For more information, read the documentation for the tmpfiles configuration file format