To gain proficiency in Ubuntu system administration, it is essential to understand the concepts of systemd units with a particular emphasis on two specific types known as targets and services. This chapter provides a basic overview of the different systemd units supported by Ubuntu and how to configure the many services that run in the background of a running Linux system.
Understanding Ubuntu systemd Targets
Ubuntu can be configured to boot into one of several states (referred to as targets), each designed to provide a specific level of operating system functionality. The system administrator configures the target to which a system will boot by default based on the purpose for which the system is being used. A desktop system, for example, will likely be configured to boot using the graphical user interface target. In contrast, a cloud-based server system would be more likely to boot to the multi-user target level.
During the boot sequence, a process named systemd looks in the /etc/systemd/system folder to find the default target setting. Having identified the default target, it proceeds to start the systemd units associated with that target so that the system boots with all the necessary processes running. For those familiar with older Ubuntu versions, systemd targets replace the older runlevel system.
Understanding Ubuntu systemd Services
A service is a process, typically running in the background, that provides specific functionality. The sshd service, for example, is the background process (also referred to as a daemon) that provides secure shell access to the system. Different systemd targets are configured to automatically launch different collections of services, depending on the functionality to be provided by that target. Targets and services are types of systemd unit, a topic that will be covered later in this chapter.
Ubuntu systemd Target Descriptions
As previously outlined, Ubuntu can be booted into one of several target levels. The default target to which the system is configured to boot will, in turn, dictate which systemd units are started. The targets that relate specifically to system startup and shutdown can be summarized as follows:
- poweroff.target – This target shuts down the system. It is unlikely you would want this as your default target.
- rescue.target – Causes the system to start in a single-user mode under which only the root user can log in. The system does not start any networking, graphical user interface, or multiuser services in this mode. This run level is ideal for system administrators to perform system maintenance or repair activities.
- multi-user.target – Boots the system into a multi-user mode with text-based console login capability.
- graphical.target – Boots the system into a networked, multi-user state with X Window System capability. By default, the graphical desktop environment will start at the end of the boot process. This is the most common run level for desktop or workstation use.
- reboot.target – Reboots the system. Another target that, for obvious reasons, you are unlikely to want as your default.
In addition to the above targets, the system includes about 70 other targets, many of which are sub-targets used by the above main targets. Behind the scenes, for example, multi-user.target will also start a target named basic.target which will, in turn, start the sockets.target unit, which is required for communication between different processes. This ensures that all the services on which the multi-user target depends are also started during the boot process.
A list of the targets and services on which a specified target is dependent can be viewed by running the following command in a terminal window:
# systemctl list-dependencies <target>Code language: plaintext (plaintext)
Figure 11-1, for example, shows a partial listing of the systemd unit dependencies for the graphical target (the complete listing contains over 140 targets and services required for a fully functional multi-user system):
The listing is presented as a hierarchical tree illustrating how some dependencies have subdependencies of their own. Scrolling to the bottom of the list, for example, would reveal that the graphical target depends on a cloud-related service called cloud-init.target, which, in turn, has its own service dependencies:
The colored dots to the left of each entry in the list indicate the current status of that service or target as follows:
- Green – The service or target is active and running.
- White – The service or target is inactive (dead). Typically because the service or target has yet to be enabled, has been stopped for some reason, or a condition on which the service or target depends has not been met.
- Red – The service or target failed to start due to a fatal error.
To find out more details about the status of a systemd unit, use the systemctl status command followed by the unit name as follows:
# systemctl status systemd-machine-id-commit.service
○ systemd-machine-id-commit.service - Commit a transient machine-id on disk
Loaded: loaded (/usr/lib/systemd/system/systemd-machine-id-commit.service; static)
Active: inactive (dead)
Condition: start condition failed at Thu 2023-03-30 08:41:05 EDT; 16min ago
└─ ConditionPathIsMountPoint=/etc/machine-id was not met
Docs: man:systemd-machine-id-commit.service(8)Code language: plaintext (plaintext)
Identifying and Configuring the Default Target
The current default target for an Ubuntu system can be identified using the systemctl command as follows:
# systemctl get-default multi-user.targetCode language: plaintext (plaintext)
In the above case, the system is configured to boot using the multi-user target by default. The default setting can be changed anytime using the systemctl command with the set-default option. The following example changes the default target to start the graphical user interface the next time the system boots:
# systemctl set-default graphical.target
Created symlink /etc/systemd/system/default.target → /usr/lib/systemd/system/graphical.target.Code language: plaintext (plaintext)
The output from the default change operation reveals the steps performed in the background by the systemctl command to implement the change. The current default is configured by establishing a symbolic link from the default.target file located in /etc/systemd/system to point to the corresponding target file located in the /usr/lib/systemd/system folder (in this case the graphical.target file).
Understanding systemd Units and Unit Types
As previously mentioned, targets and services are both types of systemd unit. All the files within the /usr/lib/systemd/system folder are called systemd unit configuration files, each representing a systemd unit. Each unit is, in turn, categorized as being of a particular unit type. Ubuntu supports 12 different unit types, including the target and service unit types already covered in this chapter.
The type of a unit file is represented by the filename extension as outlined in Table 10-1 below:
Group of systemd units.
File system auto-mount point.
Device file recognized by the kernel.
File system mount point.
File or directory in a file system.
Externally created process.
Group of hierarchically organized units that manage system processes.
Saved state of the systemd manager.
Inter-process communication socket.
Swap device or a swap file.
Note that the target unit type differs from other types in that it comprises a group of systemd units such as services or other targets.
Dynamically Changing the Current Target
The systemctl set-default command outlined previously specifies the target that will be used the next time the system starts but does not change the current system’s state. To change to a different target dynamically, use the systemctl command again, using the isolate option followed by the destination target. To switch the current system to the graphical target without rebooting, for example, the following command would be used:
# systemctl isolate graphical.targetCode language: plaintext (plaintext)
Once executed, the system will start the graphical desktop environment.
Enabling, Disabling, and Masking systemd Units
A newly installed Ubuntu system will include the base systemd service units but is unlikely to include all the services the system will eventually need once it goes into a production environment. A basic Ubuntu installation, for example, will typically not include the packages necessary to run an Apache web server, a key element of which is the apache2.service unit.
The system administrator will resolve this problem by installing the necessary apache2 packages using the following command:
# apt install apache2Code language: plaintext (plaintext)
Having configured the web server, the next task will be to check the status of the apache2 service unit to identify whether it was activated as part of the installation process:
# systemctl status apache2.service
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; disabled; vendor prese>
Active: active (running) since Mon 2023-07-17 14:01:13 UTC; 40s ago
Main PID: 22328 (apache2)
Tasks: 55 (limit: 4517)
├─22328 /usr/sbin/apache2 -k start
├─22329 /usr/sbin/apache2 -k start
└─22330 /usr/sbin/apache2 -k startCode language: plaintext (plaintext)
Note that the service status may be listed as loaded but inactive, which happens when it is preset by the vendor to be disabled when first installed. To start an inactive service, the following command can be used:
# systemctl start apache2.serviceCode language: plaintext (plaintext)
In the above example output, the status indicates that the service is disabled. This means that the next time the system reboots, the apache2 service will not start automatically and will need to be started manually by the system administrator.
To configure a service to start automatically each time the system starts, it must be enabled as follows:
# systemctl enable apache2.serviceCode language: plaintext (plaintext)
A currently running service may be stopped at any time as follows:
# systemctl stop apache2.serviceCode language: plaintext (plaintext)
Now that it has been enabled, the next time the system reboots to the current target, the apache2 service will start automatically. Assuming, for example, that the service was enabled while the system was running the multi-user target, the apache2 service will have been added as another dependency to the multi-user.target systemd unit.
Behind the scenes, systemctl adds dependencies to targets by creating symbolic links in the .wants folder for the target within the /etc/systemd/system folder. For example, the multi-user.target unit has a folder named multi-user.target.wants in /etc/systemd/system containing symbolic links to all of the systemd units located in /usr/lib/systemd/system on which it is dependent. A review of this folder will show a correlation with the dependencies listed by the systemctl list-dependencies command outlined earlier in the chapter.
To configure a service so that it no longer starts automatically as a target dependency, deactivate it as follows:
# systemctl disable apache2.serviceCode language: plaintext (plaintext)
This command will remove the symbolic link to the apache2.service unit file from the .wants directory so that it is no longer a dependency and, as such, will not be started the next time the system boots.
The .wants folder contains dependencies that, if not available, will not prevent the unit from starting and functioning. Mandatory dependencies (in other words, dependencies that will cause the unit to fail if not available) should be placed in the .requires folder (for example, multi-user. target.requires).
In addition to enabling and disabling, it is also possible to mask a systemd unit as follows:
# systemctl mask apache2.serviceCode language: plaintext (plaintext)
A masked systemd unit cannot be enabled, disabled, or started under any circumstances, even if it is listed as a dependency for another unit. As far as the system is concerned, it is as though a masked systemd unit no longer exists. This can be useful for ensuring that a unit is never started, regardless of the system conditions. The only way to regain access to the service is to unmask it:
# systemctl unmask apache2.serviceCode language: plaintext (plaintext)
Working with systemd Units in Cockpit
In addition to the command-line techniques outlined in this chapter, it is also possible to review and manage systemd units from within the Cockpit web-based interface. For example, assuming that Cockpit has been installed and set up as outlined in the chapter entitled “An Overview of the Cockpit Web Interface”, access to the list of systemd units on the system can be accessed by logging into Cockpit and selecting the Services option in the left-hand navigation panel marked A in Figure 10-3:
The row of options marked B displays units of specific types in the main area marked C, where the current status of each unit is listed in the State column.
Selecting a unit from the list will display detailed information. Figure 10-4, for example, shows the detail screen for an apache2 instance, including service logs (A) and a switch and menu (B) for performing tasks such as starting, stopping, enabling/disabling, and masking/unmasking the unit:
A newly installed Ubuntu system includes a base set of systemd units, many of which run in the background to provide much of the system’s functionality. These units are categorized by type, the most common being targets and services. A target unit is a group of other units to be started collectively. The system has a default target unit that defines the other units to be started up each time the system boots. The most common targets are those which boot the system to either multiuser or graphical mode. In addition, the systemctl command-line tool provides a range of options for performing systemd unit configuration tasks, many of which are also available through the Cockpit web-based interface.