Systemd-259.1 for SysV

Introduction to systemd for SysV

Systemd is an all-in-one package providing init (PID 1) and various services such as managing daemons, sessions, locale, etc. It can do that for the whole system (system mode, supposed to run as PID 1) or for users (user mode). For SysV, the system mode should not be needed, except that more and more packages require the user mode and the user mode relies on the system mode daemon running to start. Systemd must therefore be modified so that the system mode can run as a normal daemon (not PID 1), and does not perform all the initializations it would perform as an init system.

[Note]

Note

Development versions of BLFS may not build or run some packages properly if LFS or dependencies have been updated since the most recent stable versions of the books.

Package Information

systemd Dependencies

Required

dbus-1.16.2 (runtime)

Recommended

[Note]

Note

Linux-PAM-1.7.2 is not strictly required to build systemd, but the main reason to build systemd is for the systemd-logind daemon and the pam_systemd.so PAM module. Linux-PAM-1.7.2 is required for them. All packages in BLFS book with a dependency on systemd expect that it has been built with Linux-PAM-1.7.2.

Optional

btrfs-progs-6.17.1, cURL-8.18.0, cryptsetup-2.8.4, git-2.53.0, iptables-1.8.11, libarchive-3.8.5, libidn2-2.3.8, libpwquality-1.4.5, libseccomp-2.6.0, libxkbcommon-1.13.1, make-ca-1.16.1, p11-kit-0.26.2, qemu-10.2.0, libqrencode-4.1.1, rsync-3.4.1, sphinx-9.1.0, Valgrind-3.26.0, zsh-5.9 (for the zsh completions), AppArmor, audit-userspace, bash-completion, jekyll, kexec-tools, libbpf, libdw, libfido2, libmicrohttpd, pefile, pyelftools, quota-tools, rpm, SELinux, systemtap, tpm2-tss and Xen

Optional (to rebuild the manual pages)

docbook-xml-4.5, docbook-xsl-nons-1.79.2, libxslt-1.1.45, and lxml-6.0.2 (to build the index of systemd manual pages)

Editor Notes: https://wiki.linuxfromscratch.org/blfs/wiki/Logind

Kernel Configuration

Enable the following options in the kernel configuration and recompile the kernel if necessary:

General setup --->
  [*] Control Group support --->                                       [CGROUPS]
    [ /*] CPU controller --->                                     [CGROUP_SCHED]

File systems --->
  [*] Inotify support for userspace                               [INOTIFY_USER]
  Pseudo filesystems --->
    [*] Tmpfs virtual memory file system support (former shm fs)         [TMPFS]
    [*]   Tmpfs POSIX Access Control Lists                     [TMPFS_POSIX_ACL]

Installation of systemd

[Warning]

Warning

If a previous version of systemd has been installed, remove a service that will generate errors on following boots. As the root user:

rm -fv /usr/lib/systemd/system/systemd-update-utmp-runlevel.service

Remove some tests in the program ensuring it can only be run as PID 1 in system mode:

sed -e '/^        if (arg_action == ACTION_RUN &&$/,+4s|^|//|' \
    -i src/core/main.c &&
sed -e '/private bus only/,+2s|^|//|' \
    -i src/core/dbus.c

Remove two unneeded groups, render and sgx, from the default udev rules:

sed -i -e 's/GROUP="render"/GROUP="video"/' \
       -e 's/GROUP="sgx", //' rules.d/50-udev-default.rules.in

Build systemd by running the following commands:

mkdir build &&
cd    build &&

meson setup ..                 \
      --prefix=/usr            \
      --buildtype=release      \
      -D default-dnssec=no     \
      -D firstboot=false       \
      -D install-tests=false   \
      -D ldconfig=false        \
      -D man=auto              \
      -D sysusers=false        \
      -D rpmmacrosdir=no       \
      -D homed=disabled        \
      -D mode=release          \
      -D pam=enabled           \
      -D pamconfdir=/etc/pam.d \
      -D dev-kvm-mode=0660     \
      -D nobody-group=nogroup  \
      -D sysupdate=disabled    \
      -D ukify=disabled        \
      -D docdir=/usr/share/doc/systemd-259.1 &&

ninja

This package can only be tested on a system booted with systemd.

Installation should not overwrite already installed files from Udev in LFS. So first do a DESTDIR install:

DESTDIR=$(pwd)/dest ninja install

Then, as the root user:

pushd dest &&
   find . | while read -r p; do
      p=${p#.}
      if [ -z "$p" ]; then continue; fi
      q=${p/systemd/udev}
      if [ -e "$p" ]; then continue; fi
      if   [ -e  "$q" ] &&
         ! [ -e ."$q" ] &&
         ! [ -d ."$p" ]; then continue; fi
      if ! [ -h ."$p" ] &&
           [ -d ."$p" ]; then
         m=$(stat -c %a ."$p")
         mkdir -m $m "$p"
      else
         cp -P --preserve=mode,xattr ."$p" "$p";
      fi
   done
popd

Command Explanations

--buildtype=release: Specify a buildtype suitable for stable releases of the package, as the default may produce unoptimized binaries.

-D pamconfdir=/etc/pam.d: Forces the PAM files to be installed in /etc/pam.d rather than /usr/lib/pam.d.

-D homed=disabled: Removes a daemon that does not offer any use under a traditional BLFS configuration, especially using accounts created with useradd. To enable systemd-homed, first ensure that you have cryptsetup-2.8.4 and libpwquality-1.4.5 installed, and then change disabled to enabled in the above meson setup command.

-D ukify=disabled: Removes a script for combining a kernel, an initramfs, and a kernel command line etc. into an UEFI application which can be loaded by the UEFI firmware to start the embedded Linux kernel. It's not needed for booting a BLFS system with UEFI if following Using GRUB to Set Up the Boot Process with UEFI. And, it requires the pefile Python module at runtime, so if it's enabled but pefile is not installed, one test for it will fail in the test suite. To enable systemd-ukify, install the pefile module and then change disabled to enabled in the above meson setup command.

Configuring systemd

The /etc/pam.d/system-session file needs to be modified and a new file needs to be created in order for systemd-logind to work correctly. Run the following commands as the root user:

grep 'pam_systemd' /etc/pam.d/system-session ||
cat >> /etc/pam.d/system-session << "EOF"
# Begin Systemd addition

session  required    pam_loginuid.so
session  optional    pam_systemd.so

# End Systemd addition
EOF

cat > /etc/pam.d/systemd-user << "EOF"
# Begin /etc/pam.d/systemd-user

account  required    pam_access.so
account  include     system-account

session  required    pam_env.so
session  required    pam_limits.so
session  required    pam_loginuid.so
session  optional    pam_keyinit.so force revoke
session  optional    pam_systemd.so

auth     required    pam_deny.so
password required    pam_deny.so

# End /etc/pam.d/systemd-user
EOF

The system mode of systemd should now be restricted to only start a minimum set of daemons. As the root user:

rm -v /usr/lib/systemd/system-generators/*                 &&
grep -l systemctl      /usr/lib/udev/rules.d/* | \
    xargs sed -i '/systemctl/s/^/#/'                       &&
grep -l systemd-sysctl /usr/lib/udev/rules.d/* | \
    xargs sed -i '/systemd-sysctl/s/^/#/'                  &&
for t in sysinit.target basic.target; do
  sed -E '/^(Wants|After|Conflicts|Requires|Before)/s/^/#/' \
      /usr/lib/systemd/system/$t > /etc/systemd/system/$t
done                                                       &&
rm -rfv /usr/lib/systemd/system/sysinit.target.wants.ignore &&
mv  /usr/lib/systemd/system/sysinit.target.wants{,.ignore} &&
ln -sfv sysinit.target /etc/systemd/system/default.target   &&
mkdir -pv /etc/systemd/system/sysinit.target.wants         &&
for u in systemd-journal-catalog-update.service \
         systemd-journal-flush.service          \
         systemd-journald.service               \
         systemd-logind.service; do
  cp -v /usr/lib/systemd/system/$u /etc/systemd/system &&
  ln -sfv ../$u /etc/systemd/system/sysinit.target.wants
done                                                       &&
ln -sfv /dev/null      /etc/systemd/system/tmp.mount

Now the shutdown process of systemd has to be modified to interact nicely with SysV. This is done by introducing a unit that triggers a switch to runlevel 1 at the beginning of the systemd shutdown process and by replacing the systemd-shutdown executable with a small script. As the root user:

cat > /etc/systemd/system/telinit1.service << EOF &&
[Unit]
Description=trigger single user mode at shutdown
# Must trigger before shutting down dbus
After=dbus.service

[Service]
Type=oneshot
ExecStop=/usr/sbin/telinit 1
ExecStop=/usr/bin/sleep 1
RemainAfterExit=yes
EOF
ln -s ../telinit1.service /etc/systemd/system/sysinit.target.wants &&

mv /usr/lib/systemd/systemd-shutdown{,.orig} &&
cat > /usr/lib/systemd/systemd-shutdown <<"EOF" &&
#!/usr/bin/bash

while [ -n "$1" ]; do
   case "$1" in
      --*) shift; continue ;;
      reboot|poweroff|halt|kexec|exit) cmd="$1"; break ;;
      *) echo Unrecognized option: $1; exit 1 ;;
   esac
done
if [ -z "$cmd" ]; then echo No command given; exit 1; fi
if [ reboot = "$cmd" ]; then telinit 6
                        else telinit 0
fi
EOF
chmod a+x /usr/lib/systemd/systemd-shutdown

Boot Script

A desktop environment often runs as a group of systemd user services. Those services are spawned by the systemd per-user instance, instead of the login shell. To ensure those services get the environment variables we've set via /etc/profile.d, as the root user, install a systemd environment generator to dump all the relevant exported environment variables into the systemd per-user instance when the instance starts to run:

install -vdm755 /etc/systemd/user-environment-generators &&
cat > /etc/systemd/user-environment-generators/50-profile.sh << "EOF" &&
#!/usr/bin/env -S -i /usr/bin/bash
# SPDX-License-Identifier: MIT

. /etc/profile

# Systemd should have already set a better value for them.
unset XDG_RUNTIME_DIR
for i in $(locale); do
  unset ${i%=*}
done

# Some shell magic that we don't want to expose.
unset SHLVL

# Systemd does not want to pass functions to the environment
for i in $(declare -pF | awk '{print $3}'); do
  unset -f $i
done

python3 << _EOF
import os
for var in os.environ:
  # Simply unsetting them in shell does not work.
  if var in ['LC_CTYPE', '_']:
    continue

  print(var + '=' + os.environ[var])
_EOF
EOF

chmod -v 755 /etc/systemd/user-environment-generators/50-profile.sh

Read systemd.environment-generator(7) for details about the systemd environment generators. Note that if you've edited the content of /etc/profile.d when a desktop environment is running, you need to run the systemctl --user daemon-reload command to sync the change into the systemd per-user instance, and then log out and log in again to sync the change into the desktop environment.

To automatically start the systemd daemon when the system is rebooted, install the /etc/rc.d/init.d/systemd bootscript from the blfs-bootscripts-20260204-sysdonv package as the root user:

make install-systemd

Contents

A list of the installed files, along with their short descriptions can be found at ../../../../lfs/view/development/chapter08/systemd.html#contents-systemd.

Listed below are the newly installed programs along with short descriptions.

Installed Programs: homectl (optional), systemd-cryptenroll (if cryptsetup-2.8.4 is installed), and systemd-cryptsetup (if cryptsetup-2.8.4 is installed),

Short Descriptions

homectl

is a tool to create, remove, change, or inspect a home directory managed by systemd-homed; note that it's useless for the classic UNIX users and home directories which we are using in LFS/BLFS book

systemd-cryptenroll

Is used to enroll or remove a system from full disk encryption, as well as set and query private keys and recovery keys

systemd-cryptsetup

Attaches or removes an encrypted block device

pam_systemd.so

is a PAM module used to register user sessions with the systemd login manager, systemd-logind