8.3 Managing Services with systemd

Key Takeaways

  • systemctl start, stop, restart, and reload control a service now; enable and disable control whether it starts at boot; combine them with --now.
  • Vendor unit files live in /lib/systemd/system; local customization belongs in /etc/systemd/system or in drop-ins created by systemctl edit.
  • systemctl edit creates an override drop-in that survives package upgrades, unlike editing the vendor unit directly.
  • journalctl -u <unit> shows a service's logs; add -b for the current boot and -f to follow output live.
  • systemd targets replace SysV runlevels: multi-user.target ≈ runlevel 3, graphical.target ≈ runlevel 5, and Kali leaves network services disabled by default.
Last updated: July 2026

8.3 Managing Services with systemd

systemd is the init system and service manager on Kali (and on Debian generally). It is the first process started by the kernel (PID 1) and is responsible for bringing the system to a usable state: mounting filesystems, starting daemons, and supervising them afterward. The KLCP exam tests systemd heavily because every service you configure — Apache, PostgreSQL, SSH — is ultimately controlled through it. The primary tool is systemctl; the log viewer is journalctl.

The Core systemctl Verbs

Memorize these and, more importantly, the distinction between now and at boot:

  • systemctl start apache2 / systemctl stop apache2 — start or stop the service immediately, for this session only.
  • systemctl restart apache2 — stop then start; use when a reload cannot apply a change.
  • systemctl reload apache2 — re-read configuration without a full restart, if the service supports it.
  • systemctl enable apache2 / systemctl disable apache2 — create or remove the symlinks that make the service start automatically at boot. This says nothing about the current session.
  • systemctl enable --now apache2 — enable and start in one command, a frequently tested convenience flag.
  • systemctl status apache2 — shows active state, PID, memory, and recent log lines.
  • systemctl is-enabled apache2 / is-active apache2 — quiet checks that print enabled, disabled, static, masked, or active/inactive; ideal for scripts.

The classic exam trap is enable versus start: enabling a service does not start it, and starting a service does not make it survive a reboot. If a question says a service ran fine until the machine rebooted, the missing step was enable.

Unit Files and Where They Live

systemd manages units — services (.service), sockets, mounts, timers, targets, and more — each described by a unit file. Location matters because it determines precedence and edit policy:

DirectoryContentsEdit here?
/lib/systemd/system/ (also /usr/lib/systemd/system)Vendor unit files installed by packagesNo — upgrades overwrite them
/etc/systemd/system/Administrator's units and overridesYes
/run/systemd/system/Runtime units, created on the flyNo — lost at reboot

A file in /etc/systemd/system with the same name as one in /lib/systemd/system takes precedence entirely. But the preferred, surgical approach is systemctl edit apache2, which opens an editor and saves your changes as a drop-in file at /etc/systemd/system/apache2.service.d/override.conf. Only the directives you write there are overridden; the vendor unit stays intact, so package upgrades cannot clobber your customization. Use systemctl edit --full only when you genuinely intend to replace the whole unit, and run systemctl daemon-reload after editing unit files by hand so systemd re-reads them. systemctl cat apache2 shows the final, merged result — vendor unit plus all drop-ins.

Service States: enabled, disabled, static, masked

is-enabled reports more than two values. enabled and disabled describe boot-time symlinks. static means the unit has no [Install] section, so it cannot be enabled on its own — it is started only as a dependency of another unit. masked means the unit is symlinked to /dev/null, making it impossible to start even manually; systemctl mask apache2 and systemctl unmask apache2 manage this. Masking is a hard block, disabling is merely the absence of auto-start — a distinction exam questions exploit.

Reading Logs with journalctl

systemd captures stdout and stderr of every service into the journal. The essential invocations:

  • journalctl -u apache2 — all log entries for one unit.
  • journalctl -u apache2 -b — entries since the current boot only.
  • journalctl -u apache2 -f — follow the log live, like tail -f.
  • journalctl -p err -b — everything at error priority or worse this boot.
  • journalctl --since "1 hour ago" — time-windowed filtering that also combines with -u.

When systemctl status reports a failed service, journalctl -u is the next command you run to find the actual error message. On Debian and Kali the journal is persistent across reboots (stored under /var/log/journal), so -b 0 means this boot and -b -1 means the previous one — invaluable when a service died during startup before you could watch it.

Inspecting the System State

Beyond individual services, systemd gives you a system-wide view. systemctl list-units --type=service shows every loaded service with its state; systemctl --failed lists only units that have failed, the fastest triage command after a messy boot. systemctl list-unit-files shows every installed unit file with its enablement state, and piping it through grep is how you audit what will start at boot. For troubleshooting boot performance, systemd-analyze blame ranks units by startup time. Finally, know that systemd also ships timers (.timer units) as a modern replacement for cron jobs — systemctl list-timers shows when each will next fire.

Runlevels versus Targets

Older SysV init systems booted into numbered runlevels; systemd replaces them with named targets, which are synchronization points grouping units. The mapping the exam expects:

SysV runlevelsystemd targetMeaning
0poweroff.targetHalt
1rescue.targetSingle-user maintenance
3multi-user.targetFull multi-user, no GUI
5graphical.targetMulti-user with display manager
6reboot.targetReboot

systemctl get-default shows the boot target (graphical.target on a desktop Kali install), systemctl set-default multi-user.target changes it, and systemctl isolate rescue.target switches targets immediately.

Why Disabled-by-Default Matters on Kali

Everything above converges on Kali's security posture. A stock Kali install leaves SSH, Apache, PostgreSQL, and every other network-facing service disabled and stopped; check with systemctl is-enabled ssh and you will see disabled. You start a service for a task and stop it afterward, or you explicitly enable it knowing it will now expose a port at every boot. On the exam, any scenario describing a freshly installed Kali service that refuses connections, or asking why a service did not come back after reboot, resolves to this model: install ≠ start ≠ enable.

Test Your Knowledge

An administrator ran systemctl start apache2 and confirmed the site loads, but after rebooting Kali the web server is down again. What was missing?

A
B
C
D
Test Your Knowledge

You need to change the ExecStart options of a packaged service without your change being erased by the next package upgrade. What is the correct approach?

A
B
C
D