SYSTEMD.OFFLINE-UPDATES(7)
๐ systemd.offline-updates โ the manual page, but make it make sense ๐
okay bestie, so this is systemd.offline-updates(7) โ it's the page that explains how to do "offline" system updates with systemd. pull up a chair, grab a strawberry ๐, and let's get into it.
โจ NAME โจ
systemd.offline-updates โ Implementation of offline updates in systemd
๐ฆ IMPLEMENTING OFFLINE SYSTEM UPDATES ๐ฆ
So this page is literally telling you how to implement "offline" system updates with systemd. And when we say "offline" OS updates, we mean package installations and updates that get run while the system is booted into a special system update mode. Why? Because otherwise you get conflict drama between libraries and services that are currently running and the ones on disk. messy. ๐ This whole document was inspired by this GNOME design whiteboard[1].
Here's the logic, step by step, no cap:
- The package manager gets the system updates ready by downloading all the (.rpm or .deb or whatever) packages to update off-line into a special directory
/var/lib/system-updateโ or another directory of the package/upgrade manager's choice, live your truth. - When the user OK'ed the update, the symlink
/system-updateor/etc/system-updategets created, pointing to/var/lib/system-update(or wherever that directory with the upgrade files lives) and then the system is rebooted. And why is this symlink sitting in the root directory? Because we need to check for it very early at boot โ at a time where/var/is not available yet. it's giving "root dir or it didn't happen". ๐ - Very early in the new boot,
systemd-system-update-generator(8)checks whether/system-updateor/etc/system-updateexists. If it does, it (temporarily and for this boot only) redirects โ i.e. symlinks โdefault.targettosystem-update.target, a special target that pulls in the base system (i.e.sysinit.target, so that all file systems are mounted but little else) plus the system update units. iconic behaviour honestly. - The system now continues to boot into
default.target, and therefore intosystem-update.target. That target pulls in all system update units. Only one service should perform an update (peep the next point), and all the other ones should exit cleanly with a"success"return code and without doing anything at all. Update services should be ordered aftersysinit.targetso that the update starts after all file systems have been mounted. order matters, bestie. ๐ซถ - First step as an update service: check if the
/system-updateor/etc/system-updatesymlink points to the location used by that update service. If it doesn't exist, or it points to a different location, the service must exit without error. It is possible for multiple update services to be installed, and for multiple update services to be launched in parallel, and only the one that corresponds to the tool that created the symlink before reboot should perform any actions. Also, for the record: it is unsafe to run multiple updates in parallel. ๐ - The update service 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. And on failure, the script should revert to the old file system snapshot (without the symlink). - The update scripts should exit only after the update is finished. It is expected that the service which performs the update will cause the machine to reboot after it is done. And if
system-update.targetis successfully reached โ i.e. all update services have run โ and the/system-updateor/etc/system-updatesymlink still exists, it will be removed and the machine rebooted as a safety measure. the cleanup era we love to see. โจ - After a reboot, now that the
/system-updateand/etc/system-updatesymlink is gone, the generator will not redirectdefault.targetanymore, and the system now boots into the default target again. back to regularly scheduled programming, periodt.
๐ RECOMMENDATIONS ๐
- To make things a bit more robust, we recommend hooking the update script into
system-update.targetvia a.wants/symlink in the distribution package, rather than depending onsystemctl enablein thepostinstscriptlets of your package. More specifically: for your update script, create a.servicefile, without[Install]section, and then add a symlink like/usr/lib/systemd/system/system-update.target.wants/foobar.serviceโ../foobar.serviceto your package. - Make sure to remove the
/system-updateand/etc/system-updatesymlinks as early as possible in the update script to avoid reboot loops in case the update fails. seriously. reboot loops are not the vibe. ๐ญ - Use
FailureAction=rebootin 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'sReboot()call or callingsystemctl reboot. Seeorg.freedesktop.login1(5)for details about the logind D-Bus API. - The update service should declare
DefaultDependencies=no,Requires=sysinit.target,After=sysinit.target,After=system-update-pre.target,Before=system-update.targetand explicitly pull in any other services it requires. just lay it all out, bestie. - It may be desirable to always run an auxiliary unit when booting into offline-updates mode, which itself does not install updates. To do this, create a
.servicefile withWants=system-update-pre.targetandBefore=system-update-pre.targetand add a symlink to that file under/usr/lib/systemd/system-update.target.wants.
๐ธ SEE ALSO ๐ธ
systemd(1), systemd.generator(7), systemd-system-update-generator(8), dnf.plugin.system-upgrade(8)
๐ NOTES ๐
- GNOME design whiteboard https://wiki.gnome.org/Design/OS/SoftwareUpdates
and that's the whole page, bestie!! you ate. ๐
this was systemd 262.1, from the SYSTEMD.OFFLINE-UPDATES(7) manual โ go forth and update offline, safely, with your symlinks removed early. mwah. ๐๐ฆโจ
๐ฆ where this page comes from
- arch rolling: systemd 262.1-1 ยท LGPL-2.1-or-later AND CC0-1.0 AND GPL-2.0-or-later AND MIT-0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms