Notice: Undefined offset: 1 in /usr/local/src/wordpress/wp-content/themes/montezuma/includes/parse_php.php on line 79

HowTo: Convert Debian From SysV to Systemd

~~   Forward   ~~

For many years, Debian has used the SysV init.d system to start needed daemons and set things up.   But SysV can not work multi-threaded, and does not have controllable dependency resolution.   Upstart was invented to address some of these shortcomings, and RedHat and Ubongo tried it, but Upstart is just not extensible enough for future needs.   And so we turn to Systemd.

Systemd was developed for Linux to replace the init.d system inherited from UNIX System V and Berkeley Software Distribution (BSD) operating systems.   Unlike init.d, which is scripted, Systemd is a daemon that manages other daemons, and all daemons (including systemd) are background processes.   Systemd is the first daemon to start (during boot) and the last daemon to terminate (during shutdown).   Systemd starts each daemon, it monitors it, and it stops it in an orderly way.   And Debian will be moving to systemd when revision Jessie is released as Stable around Nov, 2014.

Why wait?   Works great.   Let’s learn and use it now as it’s a better paridigm, and brings Debian into the 21st century.

~~   Installing   ~~

# apt-get install systemd libpam-systemd systemd-sysv systemd-gui linux-headers-amd64 command-not-found

Now we’re going to modify the kernel boot commandline, so it invokes systemd during boot.   Edit /etc/default/grub and change your kernel commandline to:
GRUB_CMDLINE_LINUX_DEFAULT=”ipv6-disable=1 selinux=0 init=/lib/systemd/systemd

What we’re doing here is turning off IPV6, which is a security problem when on if you do not have your firewall specifically set for it.   And we’re turning off selinux, as it can cause problems if you haven’t gone into the extensive setup for it.   Finally we’re invoking systemd.

We’re not using the quiet parameter, because if something goes wrong we want to know where.   Also we are putting these parameters in GRUB_CMDLINE_LINUX_DEFAULT, not in GRUB_CMDLINE_LINUX, because we only want to modify the normal boot, not single-user (recovery) boot.   We want single-user to fall back on SysV in case something goes wrong with Systemd.   Now flange those changes into your system (boot block and /boot/grub/grub.cfg) with:
# update-grub
No need to modify initramfs, as we don’t need any special drivers early in the boot process for this.

We are about to reboot.   It’s important to understand that even after these changes, Debian still doesn’t run pure Systemd.   It looks in /etc/rc2.d for which daemons to start, and in cases where it has a corresponding .service file in /lib/systemd/system, it runs that.   When it doesn’t, it has a translation mechanism to run the SysV init.d script in rc2.d to start the given daemon.   Maybe with Jessie Stable we’ll have pure Systemd, but there’s just way too much brain surgery to do that for now.   But you can learn and use it.   So reboot the system.

There shouldn’t be any difference in the way boot looks now (except because quiet is off you’ll see all the boot messages scroll by).   Right, so we’re back at the desktop.   But how do we know we’re really on Systemd?
# cat /proc/1/comm
systemd

Good.

~~   About .service Files   ~~

.service files are what makes daemons go in Systemd.   They’re just a text file describing the daemon, its place in the boot chain, what user to run as, its security measures, and so on.   Now that you’re on Systemd you’ll create .service files in the correct POSIX location (/usr/local/lib/systemd/system), rather than init.d rc2.d files anymore.   The systemd daemon already knows to look for .service files here, so there’s no need to specify a path when enabling them.   .service files come in various flavors, depending on whether the daemon is an executable, script, or so on.   Here’s a summary:

Type=simple (default):   systemd considers the service to be started up immediately.   The process must not fork. Do not use this type if other services need to be ordered on this service, unless it is socket activated.
	Type=forking:   systemd considers the service started up once the process forks	and the parent has exited.   For classic daemons use this type unless you know	that it is not necessary.   You should specify PIDFile= as well so systemd can	keep track of the main process.
Type=oneshot:   this is useful for scripts that do a single job and then exit.   You may want to set RemainAfterExit=yes as well so that systemd still considers the service as active after the process has exited.
Type=dbus:   the service is considered ready when the specified BusName appears on DBus's system bus.

The ones you’ll use the most are ‘simple’ and ‘one-shot’.   Executables are almost always ‘simple’, and it’s important to know that if an executable is designed to automatically daemonize, you must disable that so Systemd can keep track of and control it.   For example, here’s my /usr/local/lib/systemd/system/unbound.service file:

[Unit]
Description=Unbound recursive Domain Name Server
After=network.service openvpn.service

[Service]
Type=simple
ExecStartPre=/usr/sbin/unbound-checkconf
ExecStart=/usr/sbin/unbound -d

Restart=always
RestartSec=60
TimeoutSec=30

# Security
PrivateTmp=yes
InaccessibleDirectories=/boot /home /media /mnt /root /srv
ReadOnlyDirectories=/bin /etc /usr
CapabilityBoundingSet=~CAP_SYS_PTRACE
DeviceAllow=/dev/null rw
NoNewPrivileges=yes

[Install]
WantedBy=multi-user.target

Notice that I had to use -d to prevent the unbound daemon from daemonizing itself (spinning off into its own little sewing machine) and forking into background?   If I didn’t use -d then systemd would start unbound, lose control of it when it spins off, kill it, start it, lose control of it, and so on, forever.   Systemd must retain control of daemons if at all possible.   If there is no switch to prevent it daemonizing (legacy app), set Type=forking.

Also you’ll notice I have a Security section;   this is optional, but I recommend it as an extra layer of security which SysV can’t provide.

~~   Managing Systemd   ~~

You don’t need to create a .service file when you install a new software package using the apt system, as they drop an init.d file in /etc/rc2.d.   Systemd will notice and invoke it on boot.   But there are times when you compile a program and don’t get an init.d file, or when you want the extra control and security that systemd has.   When you create a .system file, you must enable it, or else it’ll never start:
# systemctl enable unbound.service
ln -s /usr/local/lib/systemd/system/unbound.service /etc/systemd/system/multi-user.target.wants
Then start the service:
# systemctl start unbound.service
Did it actually start?
# systemctl status unbound.service
unbound.service – Unbound recursive Domain Name Server
Loaded: loaded (/usr/local/lib/systemd/system/unbound.service; enabled)
Active: active (running) since Thu 2015-07-17 17:04:42 PDT; 1 weeks 2 days ago
Process: 4277 ExecStartPre=/usr/sbin/unbound-checkconf (code=exited, status=0/SUCCESS)
Main PID: 4279 (unbound)
CGroup: name=systemd:/system/unbound.service
└─4279 /usr/sbin/unbound -d

Jul 17 17:04:42 cygnus unbound-checkconf[4277]: unbound-checkconf: no errors in /etc/unbound/unbound.conf
Jul 17 17:04:42 cygnus systemd[1]: Started Unbound recursive Domain Name Server.
Jul 17 17:04:42 cygnus unbound[4279]: [1405641882] unbound[4279:0] error: Could not open logfile /var/log/unbound:
Jul 17 17:04:42 cygnus unbound[4279]: [1405641882] unbound[4279:0] notice: init module 0: validator
Jul 17 17:04:42 cygnus unbound[4279]: [1405641882] unbound[4279:0] notice: init module 1: iterator
Jul 17 17:04:42 cygnus unbound[4279]: [1405641882] unbound[4279:0] info: start of service (unbound 1.4.22).

Love to see that active (running).   Notice that it first ran /usr/sbin/unbound-checkconf to check for configuration errors and all was Ok?   But whups, an embarrassing error is there too:
error: Could not open logfile /var/log/unbound.log:
… I’d forgotten to create my logfile and set its owner to the non-privileged ‘unbound’ user and group.   Easy enough to fix.

Start failure?
# journalctl -xe
Journalctl is the error logging service for Systemd. -xe tells it to jump to the end of the logfile, as your error has just occurred.

Boot problem? To get a beautiful graphical chart of the boot process:
# systemd-analyze plot > bootchart.svg

.service start fails with “Failed at step NAMESPACEspawning”?
Problem is likely in the .service Security section, usually InaccessibleDirectories.

Other useful commands:

List running units:
# systemctl

List failed units:
# systemctl –failed

List the installed unit files:
# systemctl list-unit-files

Is a unit enabled or not:
# systemctl is-enabled {unit}

Help on a unit:
# systemctl help {unit}

,'after' => '

') )