Hacking SystemD

I have been building embedded Linux systems for more than 10 years, and I have worked extensively with sysV style init. It is robust and time-tested, but it has its limitations. Several projects now aim to replace sysvinit, such as Upstart and systemd.

I work extensively with Fedora, building both nfsroot filesystems for diskless workstations, and embedded firmware based on Fedora repositories. Fedora is an odd choice for this kind of work; most people would go with Debian or Ubuntu.

Fedora migrated to systemd back in release 15. As systemd was new, I decided not to upgrade my toolchains to Fedora 15. Now we are on 17, and systemd appears stable. I therefore built an nfsroot system using Fedora 17. The result is similar to LTSP5/Meukow, except that all the packages are much newer, as Fedora ships recent releases.

Documentation on systemd is sparse, and I had some trouble working out how to trim systemd down. With sysvinit, trimming is easier: you edit rc.sysinit until it is lean, use chkconfig to turn off irrelevant services, and disable SELinux. The Fedora team has put up some useful documentation on tweaking and using systemd. They also have a sysVinit to systemd cheatsheet, and a debugging guide. These pages helped me a great deal.

My nfsroot filesystem failed to boot on the first attempt. By adding

systemd.confirm_spawn=true

to the kernel command line, I was able to confirm each command that systemd ran, and find out which one was crashing.

A useful feature of systemd is that it can run chkconfig-style commands on a chroot filesystem without chrooting into it. This is similar to yum’s --installroot option, which I used to build the filesystem in the first place. For example, to disable cron on the system you have just built, run

systemctl --system --root=$TARGET disable crond.service

Where $TARGET is the path to your chroot.

Systemd launches a number of services that cannot be disabled with the command above. Symlinks to these services/commands do not exist in /etc/systemd either. The only method I found was to delete the symlinks to these commands from /lib/systemd/system. Some of the commands that I found unnecessary in an embedded/desktop system are:

/lib/systemd/system/sysinit.target.wants/*binfmt*
/lib/systemd/system/sysinit.target.wants/cryptsetup.target
/lib/systemd/system/sysinit.target.wants/dev-hugepages.target
/lib/systemd/system/basic.target.wants/fedora-configure.service
/lib/systemd/system/local-fs.target.wants/fedora-import-state.service
/lib/systemd/system/local-fs.target.wants/fedora-readonly.service
/lib/systemd/system/local-fs.target.wants/fedora-storage-init*.service