systemd-sysext lets you layer extra files onto a running system without touching the base install, and unmerging takes them straight back off again. In this guide you will stage a directory-based system extension, check that systemd accepts it, merge its files into /usr/ and /opt/, and remove the overlay again. The same workflow also covers systemd-confext for /etc/. Allow about 15 minutes for a small test extension, plus time to build or obtain the real image.
You need a systemd host with the systemd package installed, a shell, and root access for changes to the live filesystem. This local machine has systemd 255.4-1ubuntu8.17. The commands and option names below are verified against its systemd 255 manpage and executable.
System extensions are additive runtime overlays, not packages. A sysext contributes files below /usr/ and /opt/; anything it places below /etc/ or /var/ is ignored. A confext contributes only below /etc/. While a sysext is merged, the host /usr/ and /opt/ become read-only, same as the extension itself. Do not use this workflow for a change that must survive removal or reboot unless you have a separate deployment plan.
Start with read-only commands. Use systemd-confext instead when working with configuration extensions.
systemd-sysext --no-pager --no-legend status
systemd-sysext --no-pager --no-legend list
systemctl is-enabled systemd-sysext.service
On a host with no extensions, status can report /usr none - and /opt none -, while list reports No OS extensions found. The service may show disabled, which only means boot activation is off, not that the command cannot be run by hand. It needs the privileges required to mount an overlay, so prefix any state-changing invocation with sudo.
The normal installation directory is /var/lib/extensions/. Directories in /etc/extensions/ and /run/extensions/ are also searched and are handy for small extensions or symlinks. A directory image must share its name with its release metadata file. This example creates an extension called acme-tools containing one executable. Replace the placeholder with files you have reviewed yourself.
sudo install -d -m 0755 \
/var/lib/extensions/acme-tools/usr/local/bin \
/var/lib/extensions/acme-tools/usr/lib/extension-release.d
sudo install -m 0755 ./acme-tools-check \
/var/lib/extensions/acme-tools/usr/local/bin/acme-tools-check
sudo tee /var/lib/extensions/acme-tools/usr/lib/extension-release.d/extension-release.acme-tools >/dev/null <<'EOF'
ID=ubuntu
VERSION_ID=24.04
SYSEXT_LEVEL=1
ARCHITECTURE=x86-64
EOF
The metadata is checked against the host's os-release data. In a real build, copy the matching ID, and use the host's SYSEXT_LEVEL when defined, otherwise its VERSION_ID. ARCHITECTURE is optional but worth setting when the image is not portable between architectures. Check the values before continuing:
cat /etc/os-release
cat /var/lib/extensions/acme-tools/usr/lib/extension-release.d/extension-release.acme-tools
Warning: do not put a replacement /usr/lib/os-release in the extension. It would overlay the host's own operating-system identity. The systemd 255 image policy accepts unprotected images by default, but signed or Verity-protected images are preferable for production. Treat --force as an emergency compatibility override, not a routine fix for mismatched metadata.
Ask systemd to enumerate the extension before mounting anything.
sudo systemd-sysext --no-pager --no-legend list
You should see acme-tools in the list. If it is missing, check the directory name, the .raw rule for disk images, and permissions. A directory extension must sit directly below one of the search paths, not nested in an extra project directory.
Merge every currently installed sysext image with one elevated command.
sudo systemd-sysext merge
systemd-sysext --no-pager --no-legend status
command -v acme-tools-check
The status output should show merged hierarchies, and command -v should resolve to /usr/local/bin/acme-tools-check. The file is visible as part of the merged host tree, but it is still supplied by the extension underneath. A merge fails if the hierarchies are already merged; use refresh instead after changing the installed images.
For a configuration extension, create content below /etc/, place it in /var/lib/confexts/, and run:
sudo systemd-confext list
sudo systemd-confext merge
systemd-confext --no-pager --no-legend status
Confext overlays are mounted with nosuid and, by default, noexec. --noexec=false disables the latter, and only when you have a clear reason to allow execution from the configuration overlay.
Adding or removing an image while the overlay is already mounted does not update the existing merge on its own. Use:
sudo systemd-sysext refresh
sudo systemd-sysext --no-pager --no-legend status
refresh briefly unmounts the old overlay and mounts a new one. During that short interval, extension files disappear entirely. Avoid it during a sensitive deployment or while a process depends on a supplied file. The service unit uses refresh too, whenever it starts or reloads.
Unmerge first, then remove or archive the image only once the files it supplied have actually disappeared.
sudo systemd-sysext unmerge
systemd-sysext --no-pager --no-legend status
test ! -e /usr/local/bin/acme-tools-check && echo "extension file is gone"
This removes the overlay and reveals the original host trees again. It does not delete the extension directory itself. If the extension was only a test, remove that exact directory after unmerging:
sudo rm -rf -- /var/lib/extensions/acme-tools
Destructive action: that final command is irreversible and needs elevated privileges. Verify the path carefully before pressing Enter. If you remove the wrong files, restore the extension from its build artefact or backup, then run sudo systemd-sysext refresh or merge as appropriate.
If the installed images should merge during boot, enable the service deliberately:
sudo systemctl enable systemd-sysext.service
systemctl is-enabled systemd-sysext.service
There is no per-image enable switch. Once the service is enabled, every installed image that passes discovery and compatibility checks activates automatically. To stop boot activation without deleting an image, disable the service instead, or place an empty directory with the same image name in /etc/extensions/ to mask a lower-precedence system extension.
Extensions are not a generic package manager: there is no dependency resolution. They are not a security boundary either; their files simply appear as part of the host system. Do not ship system services or systemd-sysusers definitions this way, because the service runs after the filesystems needed for discovery are already mounted. Use a portable service instead when you need service-level isolation for a disk image.
list finds the intended image and its release metadata matches the host.status shows the expected sysext or confext hierarchy merged.unmerge puts back the underlying host tree without deleting the source image.