In essence, systemd-sysext will layer a directory (or disk image) over /usr without modifying the actual filesystem.
I first learned about it by reading from the clever folks at Tailscale, but its creator Lennart Poettering has also written about it. This step-by-step article was actually most useful to me.
This is a snippet of my knit Makefile that sets up a system extension (just run
sudo make sysext
):
sysext: DESTDIR=/run/extensions/knit
sysext: install
$(INSTALL) -d /run/extensions/knit/usr/lib/extension-release.d
echo ID=_any > /run/extensions/knit/usr/lib/extension-release.d/extension-release.knit
semanage fcontext -a -e /usr /run/extensions/knit/usr
restorecon -rvF /run/extensions/knit/usr
semanage fcontext -d -e /usr /run/extensions/knit/usr
systemctl reload systemd-sysext
And now knit
and related commands are available in /usr/bin
until reboot!
One caveat is my system has SELinux enabled, so file contexts in the extension must be set appropriately; otherwise myriad things will break (including sudo!). The semanage/restorecon dance was the easiest workaround I figured out.