Stage and Verify A/B OS Updates with systemd-sysupdate
You will use systemd-sysupdate to inspect available versions, understand the transfer definitions that control them, stage an update, and decide when a reboot is safe. The installed systemd package here is 255.4-1ubuntu8.17, reporting systemd version 255. The binary is at /usr/lib/systemd/systemd-sysupdate.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow 20 to 30 minutes for inspection and a dry operational review. A real update takes as long as the download and write operations require. You need a shell, a configured sysupdate.d transfer, enough storage for another resource version, and elevated privileges for changes to system resources or systemd units.
1. Confirm the installed tool
Start with read-only checks. These do not download anything or change the machine:
$ /usr/lib/systemd/systemd-sysupdate --version
systemd 255 (255.4-1ubuntu8.17)
$ /usr/lib/systemd/systemd-sysupdate --help
The command accepts list, check-new, update, vacuum, pending, reboot and components. If you have a normal executable search path, systemd-sysupdate may be sufficient; use the full path above when checking a minimal recovery environment.
Checkpoint
This guide targets the systemd 255 interface. Do not copy options from a different release without checking that release's manual.
2. Inspect definitions and candidates
Transfer definitions are *.conf files in /etc/sysupdate.d/, /run/sysupdate.d/ or /usr/lib/sysupdate.d/. The command combines them into transfers. A component uses corresponding directories such as /etc/sysupdate.kernel.d/; discover names first:
$ sudo /usr/lib/systemd/systemd-sysupdate components
$ sudo /usr/lib/systemd/systemd-sysupdate list --no-pager
The local command may print No components defined. when no component-specific directories exist. That is not an update failure. The unqualified list command enumerates installed and downloadable versions and marks the candidate it could update to. Add a version identifier to inspect the files for one particular candidate:
$ sudo /usr/lib/systemd/systemd-sysupdate list VERSION_ID --no-pager
Replace VERSION_ID with a value from the first listing. Do not guess a version string, and do not treat a listing as proof that the update is suitable for this host. Check that all resources belonging to the transfer share the same version.
3. Understand the transfer before changing it
Each transfer file has [Transfer], [Source] and [Target] sections. A small regular-file example looks like this:
# /etc/sysupdate.d/50-example.conf
[Transfer]
ProtectVersion=%A
Verify=yes
[Source]
Type=url-file
Path=https://updates.example.invalid/os/
[email protected]
[Target]
Type=regular-file
Path=/var/lib/example-os
[email protected]
InstancesMax=2
This is a template, not a working vendor configuration. Replace the URL, names and target path with values documented by the image publisher. @v is the required version wildcard. %A expands to the running image version from IMAGE_VERSION= in /etc/os-release, so ProtectVersion=%A prevents the currently running version being removed while making room.
For an HTTP or HTTPS source, the publisher must provide a SHA256SUMS manifest. With verification enabled, systemd also checks its detached SHA256SUMS.gpg signature against the system import keyring. Payload hashes are checked regardless; leave Verify=yes outside a test environment. Partition targets must already exist. systemd-sysupdate does not create partitions, so prepare them separately with a reviewed partitioning workflow.
File names control transfer order. Definitions are processed alphabetically, and the final rename step follows that order. When several resources form one bootable OS, arrange the entry-point resource last, so an interrupted operation is less likely to expose a boot entry before its backing resources are ready.
4. Test the definition without updating
Use an alternate definitions directory when developing a configuration, rather than editing the vendor files in place:
$ sudo /usr/lib/systemd/systemd-sysupdate \
--definitions=/path/to/checked-definitions \
list --no-pager
The directory must contain the complete set of transfer files needed for the operation. A list that shows no candidates usually means a pattern, URL manifest, target path or version relationship does not match. Inspect the exact candidate with list VERSION_ID before allowing a write.
For an offline image, use --image=/path/to/disk.img. This operates on the image's file systems and is different from --root=/path/to/root, which changes where definitions are searched. Treat an image path as a write target and keep a copy or snapshot before testing an update.
5. Check and install a candidate
Check availability in a script without parsing the listing:
$ sudo /usr/lib/systemd/systemd-sysupdate check-new --no-pager
VERSION_ID
Exit status 0 means a newer candidate exists; a non-zero status means there is no candidate or the check failed. Capture the status immediately if automation needs to distinguish those cases. The command writes the candidate version when one is available.
Warning
update downloads and writes resources, and may delete older versions to satisfy InstancesMax= or available partition slots. Review the listing, storage capacity, signature setup and recovery path first:
$ sudo /usr/lib/systemd/systemd-sysupdate update VERSION_ID --no-pager
Omit VERSION_ID only when updating to the newest available version is an explicit choice. Do not add --verify=no to bypass a signature problem in production. If the operation is interrupted, the next invocation can recognise incomplete data and remove temporary material according to the transfer settings.
There is no rollback command that reconstructs a deleted version. Recovery depends on another retained version, a known-good image, or the publisher's reinstall procedure. Keep at least one protected bootable version and a tested rescue path before using this on a host.
6. Handle a pending reboot
An installed version is not necessarily the running version. Compare them with:
$ sudo /usr/lib/systemd/systemd-sysupdate pending --no-pager
$ printf 'status: %s\n' "$?"
Status 0 means a newer version is installed than the version reported by IMAGE_VERSION=. Reboot only under your normal maintenance and console-access policy. The command below reboots immediately when an update is pending, and otherwise succeeds without rebooting:
$ sudo /usr/lib/systemd/systemd-sysupdate reboot
That is disruptive. Prefer a planned reboot through your existing change process. If you use update --reboot, a newly installed version triggers an immediate reboot after the update completes.
7. Automate downloads and reboots separately
The packaged units keep these decisions separate. systemd-sysupdate.service runs the update operation and is associated with systemd-sysupdate.timer. On this system the timer starts 15 minutes after boot, repeats on an approximately two to six hour schedule, and has a persistent Saturday trigger with a random delay. The reboot pair is separate: systemd-sysupdate-reboot.service runs reboot, while its timer is scheduled around 04:10 with a 30 minute random delay.
Inspect the installed unit state before enabling anything:
$ systemctl cat systemd-sysupdate.timer systemd-sysupdate-reboot.timer
$ systemctl list-timers 'systemd-sysupdate*'
If the policy permits automatic downloads, enable only the update timer:
$ sudo systemctl enable --now systemd-sysupdate.timer
Enabling the reboot timer is a separate, service-disrupting decision:
$ sudo systemctl enable --now systemd-sysupdate-reboot.timer
Undo either enablement with the matching disable --now command. Check recent runs with systemctl status and journalctl -u systemd-sysupdate.service. Both units are conditioned not to run inside a container on this installation.
Done means
- The installed systemd version and executable path were confirmed.
listshowed the installed and available versions, and the selected candidate was inspected.- Every transfer has matching
@vpatterns and a deliberate retention policy. - Remote manifests and detached signatures are available, with verification left enabled.
- The update was treated as a write and possible deletion of old versions, with recovery prepared.
pendingwas checked before any reboot.- Download automation and reboot automation were enabled separately and can be undone.