diff --git a/Makefile-man.am b/Makefile-man.am index a7e348b1f13..a4835a533fd 100644 --- a/Makefile-man.am +++ b/Makefile-man.am @@ -144,6 +144,7 @@ MANPAGES += \ man/systemd.link.5 \ man/systemd.mount.5 \ man/systemd.nspawn.5 \ + man/systemd.offline-updates.7 \ man/systemd.path.5 \ man/systemd.preset.5 \ man/systemd.resource-control.5 \ @@ -2651,6 +2652,7 @@ EXTRA_DIST += \ man/systemd.netdev.xml \ man/systemd.network.xml \ man/systemd.nspawn.xml \ + man/systemd.offline-updates.xml \ man/systemd.path.xml \ man/systemd.preset.xml \ man/systemd.resource-control.xml \ diff --git a/man/systemd.offline-updates.xml b/man/systemd.offline-updates.xml new file mode 100644 index 00000000000..946234ad904 --- /dev/null +++ b/man/systemd.offline-updates.xml @@ -0,0 +1,169 @@ + + + + + + + + systemd.offline-updates + systemd + + + + Developer + Lennart + Poettering + lennart@poettering.net + + + + + + systemd.offline-updates + 7 + + + + systemd.offline-updates + Implementation of offline updates in systemd + + + + Implementing Offline System Updates + + This man page describes how to implement "offline" system updates with systemd. By "offline" + OS updates we mean package installations and updates that are run with the system booted into a + special system update mode, in order to avoid problems related to conflicts of libraries and + services that are currently running with those on disk. This document is inspired by this + GNOME design whiteboard. + + + The logic: + + + + The package manager prepares system updates by downloading all (RPM or DEB or + whatever) packages to update off-line in a special directory + /var/lib/system-update (or + another directory of the package/upgrade manager's choice). + + + + When the user OK'ed the update, the symlink /system-update is + created that points to /var/lib/system-update (or + wherever the directory with the upgrade files is located) and the system is rebooted. This + symlink is in the root directory, since we need to check for it very early at boot, at a + time where /var is not available yet. + + + + Very early in the new boot + systemd-update-generator8 + checks whether /system-update exists. If so, it (temporarily and for + this boot only) redirects (i.e. symlinks) default.target to + system-update.target, a special target that is pulls in the base system + (i.e. sysinit.target, so that all file systems are mounted but little + else) and the system update units. + + + + The system now continues to boot into default.target, and thus + into system-update.target. This target pulls in the system update unit, + which starts the system update script after all file systems have been mounted. + + + + As the first step, the update script should check if the + /system-update symlink points to the the location used by that update + script. In case it does not exists or points to a different location, the script must exit + without error. It is possible for multiple update services to be installed, and for multiple + update scripts to be launched in parallel, and only the one that corresponds to the tool + that created the symlink before reboot should perform any actions. It + is unsafe to run multiple updates in parallel. + + + + The update script should now do its job. If applicable and possible, it should + create a file system snapshot, then install all packages. + After completion (regardless whether the update succeeded or failed) the machine + must be rebooted, for example by calling systemctl reboot. + In addition, on failure the script should revert to the old file system snapshot + (without the symlink). + + + + The system is rebooted. Since the /system-update symlink is gone, + the generator won't redirect default.target after reboot and the + system now boots into the default target again. + + + + + + Recommendations + + + + To make things a bit more robust we recommend hooking the update script into + system-update.target via a .wants/ + symlink in the distribution package, rather than depending on systemctl + enable in the postinst scriptlets of your package. More specifically, for your + update script create a .service file, without [Install] section, and then add a symlink like + /usr/lib/systemd/system-update.target.wants/foobar.service + → ../foobar.service to your package. + + + + Make sure to remove the /system-update symlink as early as + possible in the update script to avoid reboot loops in case the update fails. + + + + Use FailureAction=reboot in the service file for your update script + to ensure that a reboot is automatically triggered if the update fails. + FailureAction= makes sure that the specified unit is activated if your + script exits uncleanly (by non-zero error code, or signal/coredump). If your script succeeds + you should trigger the reboot in your own code, for example by invoking logind's + Reboot() call or calling systemct reboot. See + logind dbus API + for details. + + + + The update service should declare DefaultDependencies=false, + and pull in any services it requires explicitly. + + + + + + See also + + + Implementing Offline System Updates, + systemd1, + systemd.generator7, + systemd-update-generator8, + dnf.plugin.system-upgrade8 + + +