Moving systemd into /usr — the technical side

Now that I think of it, I really regret I didn’t make systemd ebuild install it to /usr from the very beginning. But the harm has been done already, and I’d like to move it ASAP and that’s why I’d like to sum up problems with that and possible ways of proceeding with it.

The idea

The idea is simple as it is: move systemd install to /usr prefix completely. Right now, there are no technical benefits from keeping it in rootfs. It already depends on libdbus, which is installed in /usr, and I expect more dependencies over time. There’s no reason to move all those packages into rootfs.

Most importantly, the above information allows me to assume that such move won’t hurt our split-/usr users — because they already had to have /usr mounted for systemd to run.

The trouble

The main problem with the move is that unit files were installed into /lib location by a number of packages. The files can be moved into the new location cleanly only through rebuilding the packages which provide it. They need to stay in search path for systemd to work.

These unit files are symlinked from within /etc/systemd as well. Whenever we move a single unit, we need to update the symlink as well. I’d really like to avoid forcing users to manually fix that, and the eclass doesn’t export pkg_postinst() which could help doing it automatically.

The last problem is that people have the systemd location hardcoded into the kernel command-line. This one should be relatively easy to avoid as we can keep compatibility symlink for some time.

Solution 1: one big move

The simplest solution for the migration is to move all the relevant units in the systemd ebuild. This way, the unit integrity can be preserved, and symlinks could be updated at once as well. The risk of system breakage should be reduced to minimum.

However, there is an important disadvantage of that method. All those files would be moved out-of-scope of the Package Manager. Thus, after rebuild of every single package providing systemd units, all of our users will have to fight file collisions.

The same will likely apply to our new users, because they will have at least some units installed by random packages already. Users not ever intending to use systemd won’t be hurt because the move of unit files will be transparent to them as any other package file move.

Solution 2: temporary support for two locations

Right now, systemd already supports multiple locations for unit files. As a temporary hack, we could just add /lib/systemd/system to that list. This way, all unit files still installed in /lib will still work as expected when systemd is installed into /usr.

Sadly, this won’t handle updating /etc symlinks. I could, however, fix that easily by adding a simple .path unit or another solution updating symlinks as soon as files are removed from /lib.

Other solutions?

Well, I think the second one is the best we can do. Do you have any other ideas? I guess that udev could face a similar problem if we decide to actually move it into /usr. And there the thing is even worse because the rule install location is usually hardcoded into the ebuild or package build system itself; we will probably need to have even more degree of compatibility.

5 thoughts on “Moving systemd into /usr — the technical side”

  1. Couldn’t it be possible to make the systemd eclass do that? Any time a unit file is installed, it could check if there’s a link to its old location in /etc/systemd, and then re-link to the new version. That way there’s no hacks, and collisions (if that would cause a collision) will not be fatal.

    1. The eclass functions are called only in src_configure() or src_install(). In these phases, there’s no guarantee that the package will be actually installed, and usually writes on the outer filesystem are disallowed through sandbox.

      1. I’ve never written an eclass, but I was thinking that it can do that in src_install – it can check if a link in /etc exists and if so, makes a new link in ${D}, and then it gets merged by portage along with the package’s other files. Since the links are not owned by any package at that point, the collision will be non-fatal, and non-systemd users will not be affected since they don’t have the links anyway.

        Now that I think about it, though, this might cause a problem with buildpkg, when installing on another system with a different configuration, since I don’t think it calls src_install… would it really be difficult to add another phase to the eclass?

        1. Solution 1 results in non-fatal collisions as well then, and is much more correct. And you are correct that built packages are quite broken then because they will enable the units on other systems.

          Well, adding pkg_postinst() will hurt a lot. Ebuilds which redeclare that phase function or inherit another eclass after that one won’t get it without modifications. Ebuilds which inherit other eclasses with expected pkg_postinst() before systemd will have their pkg_postinst() eaten. So, a lot of havoc and random breakages.

  2. This is exactly what systemd cannot be used for what it meant to…
    The dependencies are too many, so it cannot be a core component.
    The whole concept is faulty.
    They should have established their own minimal IPC and wrap this using dbus as a utilitiy.

Comments are closed.