AUTHOR: Chris Wagner DATE: 2012-10-03 LICENSE: GNU Free Documentation License Version 1.2 SYNOPSIS: How to install Systemd, an alternative system and service manager, on LFS ### DESCRIPTION: I wanted to better understand the inner workings of systemd. Just having finished a LFS install on a test server, I thought LFS 7.2 might be a good basis for this. My goal was to eventually replace SysVinit completely with systemd. I fully expected lots of things to break, but was pleasantly surprised, that getting systemd to work was not all that hard. I started out with a guide from Lemon Lime which he posted on this list a year ago. Because LFS 7.2 is using a customized non-standard installation of Systemd/Udevd, additional steps were required. Systemd has matured quite a bit since last year and more distributions are using it, among them Arch Linux. Having lots of unit files available from other distributions, makes the switch a lot easier. I have everything working on my test server with a Plone CMS installed and find the built-in monitoring and logging capabilities of systemd quite remarkable. Bootup and shutdown times are considerably faster than with SysVinit. The following guide was put together as I documented the steps I took, and is intended help others to get started with systemd. I have put it in a similar format as instructions in the BLFS book to make it easier to apply. I hope you'll find this guide helpful and would welcome your comments and suggestions. ### ATTACHMENTS: see Package Information below ### PREREQUISITES: This hint requires that you have sufficient knowledge of LinuxFromScratch and be familiar with adding software from BLFS. Software versions used are from LFS 7.2 and BLFS 2012-09-14 or above. HINT: How to install Systemd-193 on LFS ======================================= Introduction to systemd ----------------------- systemd is a system and service manager for Linux, compatible with SysV and LSB init scripts. systemd provides aggressive parallelization capabilities, uses socket and D-Bus activation for starting services, offers on-demand starting of daemons, keeps track of processes using Linux control groups, supports snapshotting and restoring of the system state, maintains mount and automount points and implements an elaborate transactional dependency-based service control logic. It can work as a drop-in replacement for sysvinit. I was able to have it build and work properly using an LFS-7.2 platform. ### Package Information * Download (HTTP): `http://www.freedesktop.org/software/systemd/systemd-193.tar.xz` * Download MD5 sum: `732a9de2b1d2a15cab639c987ff9e90e` #### Required (versions from BLFS 2012-09-14) libcap2-2.22, D-Bus-1.6.4, Gperf-3.0.4, USB Utils-006, PCI Utils-3.1.10, GLib-2.32.4, (D-Bus will have to be re-installed after installing systemd!) Preparation ----------- systemd can be installed alongside SysVinit and will start any init scripts which do not have systemd equivalent unit files yet. It can also be installed to fully replace SysVinit. In this guide systemd will first be installed alongside SysVinit, then it can be tested, while optionally booting into SysVinit or systemd. When satisfied that everything works well in systemd, SysVinit can be completely replaced by systemd, and the init scripts can be removed. The required dependencies above will need a number of their own dependencies to be fulfilled and can be installed in the following order: {(attr-2.4.46), libcap2-2.22 }, {(Expat-2.1.0 or libxml2-2.8.0), D-Bus-1.6.4}, {(XML-Parser-2.41), Intltool-0.50.2}, Gperf-3.0.4, {(libusb-1.0.9), USB Utils-006}, PCI Utils-3.1.10, {(pkg-config-0.27, libffi-3.0.11, PCRE-8.31, Python-2.7.3),GLib-2.32.4} We need a Linux kernel with devtmpfs and cgroups activated while autofs4 and ipv6 is recommended. systemd will work using the default options on a 3.5.2 kernel with just the following two options added: `CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y` In `make menuconfig` these options can be found here: Device Drivers ---> Generic Driver Options ---> [*] Maintain a devtmpfs filesystem to mount at /dev [*] Automount devtmpfs at /dev, after the kernel mounted the rootfs In LFS chapter six Udev-188, a subset of systemd was installed using a LFS specific makefile. I found, that the complete systemd-188 cannot be easily installed over it, as this introduces various problems. Thus Udev-188 must be uninstalled first, which will also allow us to use a newer version of systemd than was used in LFS 7.2. As the root user stop udevd first udevadm control --exit and then remove most files from Udev-188, while keeping the LFS specific scripts: rm -v /lib/udev/rules.d/* rm -v /lib/{libudev.so.1,libudev.so.1.0.2} rm -v /usr/lib/pkgconfig/{libudev.pc,udev.pc} rm -v /usr/share/man/man7/udev.7* rm -v /usr/share/man/man8/{udevadm.8*,udevd.8*} rm -v /sbin/udevadm /usr/include/libudev.h /usr/lib/libudev.so rm -v /lib/udev/{accelerometer,ata_id,cdrom_id,collect} rm -v /lib/udev/{mtd_probe,scsi_id,udevd,v4l_id} This will leave the following 7 files in place: /lib/udev: init-net-rules.sh rule_generator.functions write_cd_rules write_net_rules /usr/share/doc/udev/lfs: 55-lfs.txt README /etc/udev/rules.d: 55-lfs.rules Installation of systemd ----------------------- `systemd-tmpfiles` requires a 'lock' group, thus as the root user, create a group: groupadd -g 54 lock Install systemd by running the following commands (you may wish to review the output from ./configure --help first and add any desired parameters to the configure command shown below): ./configure --with-distro=other \ --libexecdir=/usr/lib \ --localstatedir=/var \ --sysconfdir=/etc && make When running tests before installing sytemd, 4 out of 14 tests will fail. If run after systemd is installed, they should complete without errors. The tests also require an existing /usr/lib/udev directory. If you would like to run the unit tests, issue the following commands: mkdir -pv /usr/lib/udev/rules.d make check Now, as the root user: make install # remove static libraries rm -v /usr/lib/{libgudev-*.la,libsystemd-daemon.la} rm -v /usr/lib/{libsystemd-id128.la,libsystemd-journal.la} rm -v /usr/lib/{libsystemd-login.la,libudev.la} ln -sfv /usr/lib/systemd/systemd /bin/systemd mkdir -pv /var/log/journal Move the rule `73-seat-late.rules`, which causes an error. There are probably other rules we do not need, which could be moved out. (With the LFS version of Udev, only a subset of rules were installed.) mkdir -pv /usr/lib/udev/rules-unused/ mv -v /usr/lib/udev/rules.d/73-seat-late.rules \ /usr/lib/udev/rules-unused/ Setup /etc/machine-id, if it does not exist: systemd-machine-id-setup As the path to udevadm is hardcoded in some places, link to it: ln -sv /usr/bin/udevadm /sbin/udevadm Create other links, because udevd is no longer called udevd, but LFS init.d/udev expects it here: ln -sv /usr/lib/systemd/systemd-udevd /lib/udev/udevd ln -sv /usr/share/man/man8/systemd-udevd.8 \ /usr/share/man/man8/udevd.8 Command Explanations -------------------- `--libexecdir=/usr/lib`: Note, that D-Bus ./configure may not find systemd, when the systemd install paths are changed to be similar to the paths used by Udev-188. `--with-distro=other`: some major distributions have adapted systemd to their distribution. Others will work just fine with the default settings. Configuring systemd ------------------- ### Config Files /etc/systemd/*, /etc/dbus-1/system.d/*, /etc/hostname, /etc/vconsole.conf, /etc/locale.conf, /etc/modules-load.d/*.conf, /etc/sysctl.d/*.conf, /etc/tmpfiles.d/*.conf, /etc/binfmt.d/*.conf, /etc/os-release, /etc/machine-id, /etc/machine-info ### Configuration Information Most of the config files do not need to be modified, as the defaults will work just fine. Create /etc/hostname by running the following command as the root user grep '^HOSTNAME=' \ /etc/sysconfig/network | sed 's/^HOSTNAME=//' >/etc/hostname Adapt and create a locale file, by performing the following commands as the root user: cat > /etc/locale.conf << "EOF" LANG=en_US LC_COLLATE=C EOF We do not need to create /etc/timezone any more. In the release notes to systemd-190: "timedated will no longer write or process /etc/timezone. As we do not support late mounted /usr anymore /etc/localtime always being a symlink is now safe, and hence the information in /etc/timezone is not necessary anymore." ### Unit files for services As the root user create some unit files to start important services. Unit files of the appropriate name will mask the init scripts. Therefore systemd will use the unit file in preference over the init script, if available. This unit file creates the /run/var directory to avoid errors from LSB init scripts: cat > /etc/systemd/system/lsb-prep.service << "EOF" [Unit] Description=Network Connectivity Wants=local-fs.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/mkdir -p /run/var [Install] WantedBy=multi-user.target EOF Create sysklogd service unit files: cat > /etc/systemd/system/syslogd.service << "EOF" [Unit] Description=System Logging Service Requires=syslog.target Before=syslog.target [Service] ExecStart=/sbin/syslogd -p /run/systemd/journal/syslog -n -m 0 Sockets=syslog.socket StandardOutput=null [Install] WantedBy=multi-user.target Alias=syslog.service EOF cat > /etc/systemd/system/sysklogd.service << "EOF" [Unit] Description=System Kernel Logging Service Requisite=syslog.service BindTo=syslog.service After=syslog.service RefuseManualStart=true [Service] Type=forking StandardOutput=syslog+console StandardError=syslog+console ExecStart=/sbin/klogd -c 6 -x [Install] WantedBy=multi-user.target EOF To enable the network, create a simple unit file for a static network which uses the settings in /etc/sysconfig/ifconfig.eth0. Alternatively enable the dhcpcd at eth0.service. One could also create a unit file which will call the network/ifup scripts, that provide more functionality with multiple interfaces. Note, that this unit file requires the BROADCAST ip addr to be set in ifconfig.eth0 cat > /etc/systemd/system/network.service << "EOF" [Unit] Description=Network Connectivity Wants=network.target Before=network.target [Service] Type=oneshot RemainAfterExit=yes EnvironmentFile=/etc/sysconfig/ifconfig.eth0 ExecStart=/sbin/ip link set dev ${IFACE} up ExecStart=/sbin/ip addr add ${IP}/${PREFIX} \ broadcast ${BROADCAST} dev ${IFACE} ExecStart=/sbin/ip route add default via ${GATEWAY} ExecStop=/sbin/ip addr flush dev ${IFACE} ExecStop=/sbin/ip link set dev ${IFACE} down [Install] WantedBy=multi-user.target EOF Create the following links, which will enable essential services before rebooting into systemd: ln -sv /etc/systemd/system/lsb-prep.service \ /etc/systemd/system/multi-user.target.wants/lsb-prep.service ln -sv /etc/systemd/system/syslogd.service \ /etc/systemd/system/syslog.service ln -sv /etc/systemd/system/syslogd.service \ /etc/systemd/system/multi-user.target.wants/syslogd.service ln -sv /etc/systemd/system/sysklogd.service \ /etc/systemd/system/multi-user.target.wants/sysklogd.service ln -sv /etc/systemd/system/network.service \ /etc/systemd/system/multi-user.target.wants/network.service Add a systemd entry to grub, check the `root=` entry to match your disk: echo "menuentry \"Linux from Scratch (systemd)\" {" >> \ /boot/grub/grub.cfg echo \ " linux /boot/vmlinuz root=/dev/sda1 ro init=/bin/systemd" \ >> /boot/grub/grub.cfg echo "}" >> /boot/grub/grub.cfg Remember to rebuild and reinstall D-Bus-1.6.4, before rebooting into systemd. After booting with systemd, look at the systemd journal log from the boot process: journalctl -b Optionally Replace SysVinit --------------------------- The lfs-bootscripts scripts provide a lot of rich functionality to LFS. Care should be taken, that all required features are covered by unit files or by systemd itself, before removing them. ### Uninstall SysVinit After systemd is running well, SysVinit can be removed . Check, that no more LSB scripts are used by systemd using the following command: systemctl | grep LSB Remove the files belonging to SysVinit: rm -v /usr/bin/{last,lastb,mesg,utmpdump} rm -v /usr/include/initreq.h /etc/inittab /bin/pidof rm -v /usr/share/man/man1/{last.1*,lastb.1*,mesg.1*,utmpdump.1*} rm -v /usr/share/man/man5/{initscript.5*,inittab.5*} rm -v /usr/share/man/man8/{bootlogd.8*,fstab-decode.8*} rm -v /usr/share/man/man8/{fstab-decode.8*,init.8*} rm -v /usr/share/man/man8/{killall5.8*,pidof.8*,sulogin.8*} rm -v /sbin/{bootlogd,fstab-decode,halt,init,killall5,poweroff} rm -v /sbin/{reboot,runlevel,shutdown,sulogin,telinit} Replace sysvinit commands with links to systemd: ln -sv /usr/lib/systemd/systemd /sbin/init for tool in runlevel reboot shutdown poweroff halt telinit; do ln -svf '/usr/bin/systemctl' "/sbin/$tool" done #### Uninstall LFS-Bootscripts Now we can also move out the lfs-bootscripts and those services installed with other programs: mkdir -pv /etc/rc.bak tar -czpvf "/etc/rc.bak/rc.d-backup.tar.gz" /etc/rc.d rm -v /etc/rc.d/init.d/* for rcX in rc0 rc1 rc2 rc3 rc4 rc5 rc6 rcS; do rm -v /etc/rc.d/$rcX.d/* done The files in /etc/sysconfig, which were installed by lfs-bootscripts might still come in handy to refer to or to utilize their settings from within unit files. We could also keep ipup/ifdown for networking and the lsb functions in /lib/services. #### Mtab symlink The version of Util-linux used in LFS 7.2 contains support for systems without the /etc/mtab file, which use asymlink to `/proc/mounts` instead. Making `mtab` a symlink to `/proc/mounts` is advised by systemd, otherwise there is a reminder during boot: `/etc/mtab is not a symlink or not pointing to /proc/self/mounts. This is not supported anymore. Please make sure to replace this file by a symlink to avoid incorrect or misleading mount output.` Removing /etc/mtab earlier would cause an error in /init.d/mountfs when booting LFS via sysvinit. Now that we are not using the init scripts any more, we can make this change: ln -svf /proc/mounts /etc/mtab Contents -------- **Installed Programs:** systemctl, journalctl, udevadm, systemd-udevd, ... **Installed Libraries:** libudev.so, libgudev-1.0.so, libsystemd-daemon.so, libsystemd-id128.so, libsystemd-journal.so, libsystemd-login.so **Installed Directories:** /etc/systemd/, /usr/include/systemd/, /usr/lib/udev/, /usr/lib/systemd/ ### Short Descriptions * _systemctl_ may be used to control the state of the systemd system and service manager * _journalctl_ may be used to query the contents of the systemd journal as written by systemd-journald.service ### Further information: [ Official Website ]( http://www.freedesktop.org/wiki/Software/systemd ) [ Arch Linux Wiki ]( https://wiki.archlinux.org/index.php/Systemd ) ### ACKNOWLEDGEMENTS: * Lemon Lime who posted a similar guide on lfs-dev in Aug. 2011 * Matthew Burgess and Bruce Dubbs for encouraging me to publish this as a hint ### CHANGELOG: [2012-10-03] * Initial hint.