Skip to content
rodolfo.gg
Go back

Guide for service administration with systemd.

CC BY-NC-ND 4.0
Rodolfo González González

Guide for service administration with systemd.

Introduction

A long, long time ago, I started administering a Solaris server for a few months. From there I moved to Slackware, because that was what was available. And then to Red Hat. In those days, the service lifecycle was handled without complications using SysVinit. However, at some point along the way, someone had the idea of complicating things.

Enter systemd.

And, well, since Ubuntu, Debian and most derived distributions use this system, there is no choice but to learn a little about it.


Table of contents

Table of contents

1. Introduction: what is systemd and what does it manage

systemd is the initialization system and service manager predominant in many modern Linux distributions. Its main process typically runs as PID 1 and is responsible for booting the system, managing services, mounting filesystems, starting sockets, scheduling tasks, handling sessions, collecting logs through journald and coordinating dependencies between system components.

In daily administration, the central command is systemctl. With it, systemd units are queried, started, stopped, enabled, disabled, restarted, reloaded, masked and managed.

A “service” in systemd typically corresponds to a unit with the .service extension, for example:

However, systemd does not only manage services. It manages different types of units: services, sockets, timers, targets, mounts, automounts, paths, slices, scopes, devices and swaps.

Basic example to check the status of a service:

Terminal window
systemctl status ssh.service

Command explanation:

Alternative example:

Terminal window
systemctl status ssh

This command usually resolves ssh to ssh.service, as long as there is no ambiguity with another unit of the same name and different extension.


2. Core concepts: units, services and targets

2.1 Unit

A unit is an object managed by systemd. Each unit is defined by a configuration file called a unit file. The unit name indicates its type through its extension.

Examples:

nginx.service
ssh.socket
apt-daily.timer
multi-user.target
home.mount

2.2 Service

A .service unit describes how to start, stop, reload and supervise a process or set of processes.

Example of a minimal service file:

[Unit]
Description=Example service
After=network.target
[Service]
ExecStart=/usr/local/bin/my-service
Restart=on-failure
[Install]
WantedBy=multi-user.target

Section explanation:

2.3 Target

A target is a unit that groups other units. It is roughly comparable to the old SysVinit runlevels.

Common targets:

View the default target:

Terminal window
systemctl get-default

Explanation:

Set the default target:

Terminal window
sudo systemctl set-default multi-user.target

Explanation:

Example for a server without a graphical desktop:

Terminal window
sudo systemctl set-default multi-user.target

Example for a workstation with graphical environment:

Terminal window
sudo systemctl set-default graphical.target

3. Basic system and service inspection

Before installing, modifying or removing services, it is useful to know how to inspect the system state.

3.1 List active services

Terminal window
systemctl list-units --type=service --state=running

Explanation:

Example:

Terminal window
systemctl list-units --type=service --state=running

Useful for checking which processes are currently being managed by systemd.

3.2 List all loaded services

Terminal window
systemctl list-units --type=service --all

Explanation:

Example:

Terminal window
systemctl list-units --type=service --all

3.3 List installed unit files

Terminal window
systemctl list-unit-files --type=service

Explanation:

The output typically includes states such as:

Example:

Terminal window
systemctl list-unit-files --type=service | grep nginx

3.4 View the detailed status of a service

Terminal window
systemctl status nginx.service

Explanation:

Example:

Terminal window
systemctl status nginx.service

Typical abbreviated output:

● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since ...
Main PID: 1234 (nginx)
Tasks: 5
Memory: 12.3M

3.5 View internal properties of a unit

Terminal window
systemctl show nginx.service

Explanation:

Example filtering a property:

Terminal window
systemctl show nginx.service --property=MainPID

Explanation:

Another example:

Terminal window
systemctl show nginx.service --property=FragmentPath --property=DropInPaths

Explanation:

3.6 View the effective unit file

Terminal window
systemctl cat nginx.service

Explanation:

Example:

Terminal window
systemctl cat nginx.service

4. Service installation

Installing a service can mean two different things:

  1. Installing a system package that includes its own systemd service.
  2. Manually creating and installing a .service file for a custom application.

This section covers installation via package managers. Manual creation is covered in the next section.

4.1 Install a service on Debian, Ubuntu and derivatives

Example with nginx:

Terminal window
sudo apt update
sudo apt install nginx

First command explanation:

Second command explanation:

Full example:

Terminal window
sudo apt update
sudo apt install nginx
systemctl status nginx.service

After installing a package, it is useful to verify whether the service is active or enabled:

Terminal window
systemctl is-active nginx.service
systemctl is-enabled nginx.service

Explanation:

4.2 Install a service on Fedora, RHEL, CentOS Stream, Rocky Linux or AlmaLinux

Example with nginx:

Terminal window
sudo dnf install nginx

Explanation:

Full example:

Terminal window
sudo dnf install nginx
systemctl status nginx.service

In many Red Hat family distributions, installing a package does not necessarily mean starting or enabling it. To enable and start it:

Terminal window
sudo systemctl enable --now nginx.service

Explanation:

4.3 Install a service on Arch Linux and derivatives

Example with nginx:

Terminal window
sudo pacman -Syu nginx

Explanation:

Then it can be enabled and started:

Terminal window
sudo systemctl enable --now nginx.service

4.4 View which files a package installed

On Debian/Ubuntu:

Terminal window
dpkg -L nginx | grep systemd

Explanation:

Example:

Terminal window
dpkg -L nginx | grep '\.service$'

Explanation:

On Fedora/RHEL:

Terminal window
rpm -ql nginx | grep '\.service$'

Explanation:


5. Manual creation of custom services

When an application does not come packaged as a systemd service, a unit can be created manually.

5.1 Example custom application

Suppose there is a binary at:

/usr/local/bin/miapp

And we want to run it as a service.

First, it is recommended to create a dedicated system user:

Terminal window
sudo useradd --system --home /var/lib/miapp --create-home --shell /usr/sbin/nologin miapp

Explanation:

In some distributions the nologin path may be different. It can be verified with:

Terminal window
command -v nologin

5.2 Create directories for the application

Terminal window
sudo mkdir -p /etc/miapp /var/lib/miapp /var/log/miapp
sudo chown -R miapp:miapp /var/lib/miapp /var/log/miapp
sudo chmod 0750 /var/lib/miapp /var/log/miapp

Explanation:

5.3 Create the unit file

Terminal window
sudo editor /etc/systemd/system/miapp.service

Suggested content:

[Unit]
Description=My example application
Documentation=https://example.com/docs/miapp
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=miapp
Group=miapp
WorkingDirectory=/var/lib/miapp
EnvironmentFile=-/etc/miapp/miapp.env
ExecStart=/usr/local/bin/miapp --config /etc/miapp/config.yaml
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30s
TimeoutStopSec=30s
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target

[Unit] explanation:

[Service] explanation:

[Install] explanation:

5.4 Reload systemd after creating or modifying a unit

Terminal window
sudo systemctl daemon-reload

Explanation:

Full example:

Terminal window
sudo editor /etc/systemd/system/miapp.service
sudo systemctl daemon-reload
sudo systemctl status miapp.service

5.5 Verify syntax of a unit

Terminal window
systemd-analyze verify /etc/systemd/system/miapp.service

Explanation:

Example:

Terminal window
systemd-analyze verify /etc/systemd/system/miapp.service

If the command prints no errors, the unit is probably syntactically valid.

5.6 Enable and start the custom service

Terminal window
sudo systemctl enable --now miapp.service

Explanation:

Verify:

Terminal window
systemctl status miapp.service
journalctl -u miapp.service -n 50 --no-pager

Explanation:


6. Starting, stopping, restarting and reloading services

6.1 Start a service

Terminal window
sudo systemctl start nginx.service

Explanation:

Example:

Terminal window
sudo systemctl start nginx.service
systemctl status nginx.service

6.2 Stop a service

Terminal window
sudo systemctl stop nginx.service

Explanation:

Example:

Terminal window
sudo systemctl stop nginx.service
systemctl is-active nginx.service

6.3 Restart a service

Terminal window
sudo systemctl restart nginx.service

Explanation:

Example:

Terminal window
sudo nginx -t
sudo systemctl restart nginx.service

Explanation:

6.4 Reload a service without restarting it

Terminal window
sudo systemctl reload nginx.service

Explanation:

Example:

Terminal window
sudo nginx -t
sudo systemctl reload nginx.service

6.5 Reload if possible, restart if not

Terminal window
sudo systemctl reload-or-restart nginx.service

Explanation:

Example:

Terminal window
sudo systemctl reload-or-restart nginx.service

6.6 Restart only if the service is already active

Terminal window
sudo systemctl try-restart nginx.service

Explanation:

Example:

Terminal window
sudo systemctl try-restart nginx.service

6.7 Reload or restart only if active

Terminal window
sudo systemctl reload-or-try-restart nginx.service

Explanation:

Example:

Terminal window
sudo systemctl reload-or-try-restart nginx.service

6.8 Kill service processes

Terminal window
sudo systemctl kill nginx.service

Explanation:

Example sending SIGKILL:

Terminal window
sudo systemctl kill --signal=SIGKILL nginx.service

Explanation:

Example sending SIGHUP:

Terminal window
sudo systemctl kill --signal=SIGHUP nginx.service

Explanation:


7. Enabling, disabling, masking and unmasking services

In systemd, it is important to distinguish between starting and enabling:

7.1 Enable a service to start automatically

Terminal window
sudo systemctl enable nginx.service

Explanation:

Example:

Terminal window
sudo systemctl enable nginx.service
systemctl is-enabled nginx.service

7.2 Enable and start in one step

Terminal window
sudo systemctl enable --now nginx.service

Explanation:

Example:

Terminal window
sudo systemctl enable --now nginx.service
systemctl status nginx.service

7.3 Disable a service

Terminal window
sudo systemctl disable nginx.service

Explanation:

Example:

Terminal window
sudo systemctl disable nginx.service
systemctl is-enabled nginx.service
systemctl is-active nginx.service

7.4 Disable and stop in one flow

There is no single traditional subcommand equivalent to “disable —now” in all historical versions, although many modern versions accept disable --now. For maximum compatibility, it can be done explicitly:

Terminal window
sudo systemctl disable nginx.service
sudo systemctl stop nginx.service

Explanation:

Example using --now when available:

Terminal window
sudo systemctl disable --now nginx.service

Explanation:

7.5 Re-enable a service

Terminal window
sudo systemctl reenable nginx.service

Explanation:

Example:

Terminal window
sudo systemctl reenable nginx.service

7.6 Mask a service

Terminal window
sudo systemctl mask nginx.service

Explanation:

Example:

Terminal window
sudo systemctl mask nginx.service
systemctl status nginx.service

Conceptual output:

Loaded: masked (Reason: Unit nginx.service is masked.)

7.7 Mask and stop immediately

Terminal window
sudo systemctl mask --now nginx.service

Explanation:

Example:

Terminal window
sudo systemctl mask --now nginx.service

7.8 Unmask a service

Terminal window
sudo systemctl unmask nginx.service

Explanation:

Example:

Terminal window
sudo systemctl unmask nginx.service
sudo systemctl enable --now nginx.service

7.9 Check if a service is active or enabled

Terminal window
systemctl is-active nginx.service
systemctl is-enabled nginx.service

Explanation:

Example in a script:

Terminal window
if systemctl is-active --quiet nginx.service; then
echo "Nginx is active"
else
echo "Nginx is not active"
fi

Explanation:


8. Service configuration with unit files and drop-ins

8.1 Do not directly edit package files

Services installed by packages usually have their units at paths such as:

/usr/lib/systemd/system/
/lib/systemd/system/

Depending on the distribution, one or the other may be the main path. It is not advisable to edit these files directly, because a package update may overwrite changes.

The recommended location for local changes is:

/etc/systemd/system/

8.2 Edit a service with a drop-in

Terminal window
sudo systemctl edit nginx.service

Explanation:

Example to add automatic restart:

Terminal window
sudo systemctl edit nginx.service

Contents:

[Service]
Restart=on-failure
RestartSec=3s

Then:

Terminal window
sudo systemctl daemon-reload
sudo systemctl restart nginx.service

Explanation:

8.3 Edit the complete unit file

Terminal window
sudo systemctl edit --full nginx.service

Explanation:

Example:

Terminal window
sudo systemctl edit --full nginx.service
sudo systemctl daemon-reload
sudo systemctl restart nginx.service

8.4 View differences between original files and overrides

Terminal window
systemd-delta

Explanation:

Example:

Terminal window
systemd-delta --type=extended

Explanation:

Another example:

Terminal window
systemd-delta nginx.service

8.5 Reset overrides of a unit

To remove a drop-in created with systemctl edit:

Terminal window
sudo rm -rf /etc/systemd/system/nginx.service.d
sudo systemctl daemon-reload
sudo systemctl restart nginx.service

Explanation:

If systemctl edit --full was used, the full copy must be deleted:

Terminal window
sudo rm -f /etc/systemd/system/nginx.service
sudo systemctl daemon-reload
sudo systemctl restart nginx.service

Explanation:

8.6 Override lists in drop-ins

Some systemd directives accept multiple values. To completely replace them in a drop-in, they must first be cleared.

Example with ExecStart:

[Service]
ExecStart=
ExecStart=/usr/local/bin/miapp --modo produccion

Explanation:

Full example:

Terminal window
sudo systemctl edit miapp.service

Contents:

[Service]
ExecStart=
ExecStart=/usr/local/bin/miapp --config /etc/miapp/prod.yaml

Apply:

Terminal window
sudo systemctl daemon-reload
sudo systemctl restart miapp.service

8.7 Configure automatic restarts

Drop-in:

[Service]
Restart=on-failure
RestartSec=10s
StartLimitIntervalSec=300
StartLimitBurst=5

Explanation:

Commands:

Terminal window
sudo systemctl edit miapp.service
sudo systemctl daemon-reload
sudo systemctl restart miapp.service

8.8 Configure dependencies and boot order

Example:

[Unit]
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

Explanation:

Drop-in example:

Terminal window
sudo systemctl edit miapp.service

Contents:

[Unit]
After=network-online.target postgresql.service
Wants=network-online.target
Requires=postgresql.service

Apply:

Terminal window
sudo systemctl daemon-reload
sudo systemctl restart miapp.service

9. Environment variables, users, permissions and working directories

9.1 Inline environment variables

[Service]
Environment="APP_ENV=production" "APP_PORT=8080"

Explanation:

Example:

Terminal window
sudo systemctl edit miapp.service

Contents:

[Service]
Environment="APP_ENV=production" "LOG_LEVEL=info"

Apply:

Terminal window
sudo systemctl daemon-reload
sudo systemctl restart miapp.service

9.2 Variables from EnvironmentFile

File:

Terminal window
sudo install -d -m 0750 -o root -g miapp /etc/miapp
sudo editor /etc/miapp/miapp.env

File contents:

Terminal window
APP_ENV=production
APP_PORT=8080
LOG_LEVEL=info

Unit file:

[Service]
EnvironmentFile=/etc/miapp/miapp.env

Explanation:

[Service]
EnvironmentFile=-/etc/miapp/miapp.env

Full example:

Terminal window
sudo editor /etc/miapp/miapp.env
sudo systemctl restart miapp.service

Note: if only the content of EnvironmentFile changes, restarting the service is usually sufficient. If the unit file is changed to add or remove the EnvironmentFile= directive, then daemon-reload is required.

9.3 Run as a dedicated user

[Service]
User=miapp
Group=miapp

Explanation:

User creation example:

Terminal window
sudo useradd --system --home /var/lib/miapp --create-home --shell /usr/sbin/nologin miapp

9.4 Configure working directory

[Service]
WorkingDirectory=/var/lib/miapp

Explanation:

Example:

[Service]
WorkingDirectory=/opt/miapp
ExecStart=/opt/miapp/bin/miapp

9.5 Automatically create directories with systemd

systemd can create runtime, state, cache and log directories for a service.

Example:

[Service]
User=miapp
Group=miapp
RuntimeDirectory=miapp
StateDirectory=miapp
CacheDirectory=miapp
LogsDirectory=miapp

Explanation:

Usage example:

[Service]
User=miapp
Group=miapp
StateDirectory=miapp
WorkingDirectory=/var/lib/miapp
ExecStart=/usr/local/bin/miapp

9.6 Use DynamicUser

[Service]
DynamicUser=yes
StateDirectory=miapp
ExecStart=/usr/local/bin/miapp

Explanation:

Example:

[Unit]
Description=Service with dynamic user
[Service]
DynamicUser=yes
StateDirectory=miapp
ExecStart=/usr/local/bin/miapp --data-dir /var/lib/miapp
[Install]
WantedBy=multi-user.target

10. Logs, diagnostics and troubleshooting

10.1 View logs for a service

Terminal window
journalctl -u nginx.service

Explanation:

Example:

Terminal window
journalctl -u nginx.service

10.2 View last log lines

Terminal window
journalctl -u nginx.service -n 100 --no-pager

Explanation:

Example:

Terminal window
journalctl -u nginx.service -n 100 --no-pager

10.3 Follow logs in real time

Terminal window
journalctl -u nginx.service -f

Explanation:

Example:

Terminal window
journalctl -u miapp.service -f

10.4 View logs from the last boot

Terminal window
journalctl -u nginx.service -b

Explanation:

Example:

Terminal window
journalctl -u nginx.service -b --no-pager

10.5 View logs from a previous boot

Terminal window
journalctl --list-boots

Explanation:

Then:

Terminal window
journalctl -b -1 -u nginx.service

Explanation:

10.6 View system errors

Terminal window
journalctl -p err -b

Explanation:

Example:

Terminal window
journalctl -p warning..alert -b --no-pager

Explanation:

10.7 Diagnose failed services

Terminal window
systemctl --failed

Explanation:

Example:

Terminal window
systemctl --failed

View details of a failed unit:

Terminal window
systemctl status miapp.service
journalctl -u miapp.service -b -n 200 --no-pager

10.8 Reset failed status

Terminal window
sudo systemctl reset-failed miapp.service

Explanation:

Example:

Terminal window
sudo systemctl reset-failed miapp.service
systemctl status miapp.service

Reset all recorded failures:

Terminal window
sudo systemctl reset-failed

10.9 Check boot times

Terminal window
systemd-analyze

Explanation:

Example:

Terminal window
systemd-analyze blame

Explanation:

Example with critical path:

Terminal window
systemd-analyze critical-chain

Explanation:

10.10 View dependency tree

Terminal window
systemctl list-dependencies nginx.service

Explanation:

Reverse example:

Terminal window
systemctl list-dependencies --reverse nginx.service

Explanation:


11. Uninstalling, removing and cleaning up services

This section distinguishes several operations that are often confused.

11.1 Stop before uninstalling

Terminal window
sudo systemctl stop nginx.service

Explanation:

11.2 Disable before uninstalling

Terminal window
sudo systemctl disable nginx.service

Explanation:

Combined example:

Terminal window
sudo systemctl disable --now nginx.service

Explanation:

11.3 Uninstall a package on Debian/Ubuntu

Remove the package keeping configuration:

Terminal window
sudo apt remove nginx

Explanation:

Remove the package and purge configuration managed by the package:

Terminal window
sudo apt purge nginx

Explanation:

Remove unused dependencies:

Terminal window
sudo apt autoremove

Explanation:

Full example:

Terminal window
sudo systemctl disable --now nginx.service
sudo apt purge nginx
sudo apt autoremove

11.4 Uninstall a package on Fedora/RHEL

Terminal window
sudo dnf remove nginx

Explanation:

Example:

Terminal window
sudo systemctl disable --now nginx.service
sudo dnf remove nginx

11.5 Uninstall a package on Arch Linux

Terminal window
sudo pacman -R nginx

Explanation:

Remove package and unused dependencies installed as dependencies:

Terminal window
sudo pacman -Rs nginx

Explanation:

Example:

Terminal window
sudo systemctl disable --now nginx.service
sudo pacman -Rs nginx

11.6 Remove a manual service created in /etc/systemd/system

Suppose it was created manually:

/etc/systemd/system/miapp.service

Recommended process:

Terminal window
sudo systemctl disable --now miapp.service
sudo rm -f /etc/systemd/system/miapp.service
sudo systemctl daemon-reload
sudo systemctl reset-failed miapp.service

Explanation:

If the service had drop-ins:

Terminal window
sudo rm -rf /etc/systemd/system/miapp.service.d
sudo systemctl daemon-reload

Explanation:

11.7 Remove data, logs and configuration from a custom application

After removing the unit file, if you want to completely remove the application:

Terminal window
sudo rm -rf /etc/miapp /var/lib/miapp /var/log/miapp /var/cache/miapp

Explanation:

Safer example, listing first:

Terminal window
sudo find /etc/miapp /var/lib/miapp /var/log/miapp /var/cache/miapp -maxdepth 2 -print

Then, if the paths are confirmed correct:

Terminal window
sudo rm -rf /etc/miapp /var/lib/miapp /var/log/miapp /var/cache/miapp

11.8 Remove a service user and group

Terminal window
sudo userdel miapp

Explanation:

If you also want to delete the home directory, depending on how it was created:

Terminal window
sudo userdel --remove miapp

Explanation:

Note: if the home directory was shared, contains necessary data or is in a sensitive path, it is advisable to review manually first.

11.9 Clean up orphan or not-found units

After manually removing services:

Terminal window
sudo systemctl daemon-reload
systemctl list-units --type=service --all | grep miapp

If it appears as failed:

Terminal window
sudo systemctl reset-failed miapp.service

If it appears as masked:

Terminal window
sudo systemctl unmask miapp.service
sudo systemctl daemon-reload

11.10 Remove a manually masked service

If a symlink like this exists:

/etc/systemd/system/miapp.service -> /dev/null

It can be unmasked:

Terminal window
sudo systemctl unmask miapp.service

Or review manually:

Terminal window
ls -l /etc/systemd/system/miapp.service

If it is confirmed to be a symlink to /dev/null:

Terminal window
sudo rm -f /etc/systemd/system/miapp.service
sudo systemctl daemon-reload

12. User services: systemd —user

systemd can also manage per-user services, without root privileges. These services belong to the user session and are normally configured under:

~/.config/systemd/user/

12.1 Create a user service

Terminal window
mkdir -p ~/.config/systemd/user
editor ~/.config/systemd/user/mi-tarea.service

Contents:

[Unit]
Description=Example user service
[Service]
ExecStart=/home/usuario/bin/mi-tarea
Restart=on-failure
[Install]
WantedBy=default.target

Explanation:

12.2 Reload user units

Terminal window
systemctl --user daemon-reload

Explanation:

12.3 Enable and start a user service

Terminal window
systemctl --user enable --now mi-tarea.service

Explanation:

12.4 View user logs

Terminal window
journalctl --user -u mi-tarea.service

Explanation:

12.5 Allow user services to persist after logout

Terminal window
loginctl enable-linger usuario

Explanation:

Example:

Terminal window
sudo loginctl enable-linger deploy

This is useful for user services run by a deployment account.

Disable linger:

Terminal window
sudo loginctl disable-linger deploy

13. Timers: practical replacement for cron for periodic services

systemd timers allow services to be run on a schedule.

13.1 Create a service executable by a timer

File:

Terminal window
sudo editor /etc/systemd/system/backup-miapp.service

Contents:

[Unit]
Description=MiApp Backup
[Service]
Type=oneshot
User=miapp
Group=miapp
ExecStart=/usr/local/bin/backup-miapp

Explanation:

13.2 Create the timer

File:

Terminal window
sudo editor /etc/systemd/system/backup-miapp.timer

Contents:

[Unit]
Description=Runs MiApp backup daily
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true
Unit=backup-miapp.service
[Install]
WantedBy=timers.target

Explanation:

13.3 Enable and start the timer

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now backup-miapp.timer

Explanation:

13.4 List timers

Terminal window
systemctl list-timers --all

Explanation:

Example:

Terminal window
systemctl list-timers --all | grep backup-miapp

13.5 Manually run the timer service

Terminal window
sudo systemctl start backup-miapp.service

Explanation:


14. Security and service hardening

systemd allows applying isolation measures without modifying the application.

14.1 Protect the filesystem

Drop-in example:

[Service]
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/miapp /var/log/miapp

Explanation:

Apply:

Terminal window
sudo systemctl edit miapp.service
sudo systemctl daemon-reload
sudo systemctl restart miapp.service

14.2 Restrict privileges

[Service]
NoNewPrivileges=true
PrivateTmp=true
PrivateDevices=true

Explanation:

14.3 Restrict Linux capabilities

[Service]
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE

Explanation:

Example for an application listening on port 80:

[Service]
User=miapp
Group=miapp
AmbientCapabilities=CAP_NET_BIND_SERVICE
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
ExecStart=/usr/local/bin/miapp --listen :80

14.4 Analyze security of a unit

Terminal window
systemd-analyze security miapp.service

Explanation:

Example:

Terminal window
systemd-analyze security nginx.service

14.5 Reasonable hardening of a custom service

Example:

[Service]
User=miapp
Group=miapp
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
ReadWritePaths=/var/lib/miapp /var/log/miapp
Restart=on-failure

Explanation:


15. Operational best practices

15.1 Use clear names

For custom services, use descriptive names:

miapp-api.service
miapp-worker.service
miapp-scheduler.service

This facilitates logging, monitoring and administration.

15.2 Use dedicated users

Avoid running services as root unless strictly necessary. Use:

[Service]
User=miapp
Group=miapp

15.3 Separate configuration, data and binaries

Common convention:

/usr/local/bin/miapp # manually installed binary
/etc/miapp/ # configuration
/var/lib/miapp/ # persistent data
/var/log/miapp/ # own logs, if applicable
/run/miapp/ # temporary runtime files

15.4 Validate before restarting

Example with Nginx:

Terminal window
sudo nginx -t && sudo systemctl reload nginx.service

Explanation:

Example with a custom application that supports validation:

Terminal window
/usr/local/bin/miapp --check-config /etc/miapp/config.yaml && sudo systemctl restart miapp.service

15.5 Use drop-ins for local changes

Preferred:

Terminal window
sudo systemctl edit miapp.service

Avoid, unless justified:

Terminal window
sudo editor /usr/lib/systemd/system/miapp.service

Reason: files under /usr/lib/systemd/system or /lib/systemd/system usually belong to packages and may be overwritten by updates.

15.6 Document overrides

A drop-in can include comments:

[Service]
# Automatic restart to tolerate transient network failures.
Restart=on-failure
RestartSec=5s

15.7 Review logs after any change

Terminal window
sudo systemctl restart miapp.service
systemctl status miapp.service
journalctl -u miapp.service -b -n 100 --no-pager

15.8 Avoid rm -rf without verifying paths

Before deleting data:

Terminal window
sudo find /var/lib/miapp -maxdepth 2 -print

Then, if confirmed:

Terminal window
sudo rm -rf /var/lib/miapp

15.9 Use daemon-reload when appropriate

Should be used after:

Command:

Terminal window
sudo systemctl daemon-reload

Not usually necessary after modifying only a file loaded with EnvironmentFile=, unless the unit file itself was changed.

15.10 Differentiate reload from daemon-reload

Terminal window
sudo systemctl reload nginx.service

Reloads the Nginx configuration.

Terminal window
sudo systemctl daemon-reload

Reloads the systemd configuration, that is, the unit files.

These are different operations.


16. Important directories and files

16.1 System unit files

/etc/systemd/system/

Use:

Examples:

/etc/systemd/system/miapp.service
/etc/systemd/system/nginx.service.d/override.conf
/etc/systemd/system/multi-user.target.wants/nginx.service

/usr/lib/systemd/system/

Use:

Examples:

/usr/lib/systemd/system/sshd.service
/usr/lib/systemd/system/docker.service

/lib/systemd/system/

Use:

Examples:

/lib/systemd/system/ssh.service
/lib/systemd/system/nginx.service

/run/systemd/system/

Use:


16.2 User unit files

~/.config/systemd/user/

Use:

Example:

/home/usuario/.config/systemd/user/mi-tarea.service

/etc/systemd/user/

Use:


/usr/lib/systemd/user/

Use:


16.3 General systemd configuration

/etc/systemd/system.conf

Use:


/etc/systemd/user.conf

Use:


/etc/systemd/journald.conf

Use:


/etc/systemd/logind.conf

Use:


16.4 Journal logs

/run/log/journal/

Use:


/var/log/journal/

Use:

Create persistent journal storage:

Terminal window
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald.service

Explanation:


16.5 Application configuration

/etc/<service>/

Use:

Examples:

/etc/nginx/
/etc/ssh/
/etc/postgresql/
/etc/miapp/

16.6 Persistent data

/var/lib/<service>/

Use:

Examples:

/var/lib/postgresql/
/var/lib/mysql/
/var/lib/docker/
/var/lib/miapp/

16.7 Classic file-based logs

/var/log/<service>/

Use:

Examples:

/var/log/nginx/
/var/log/apache2/
/var/log/miapp/

16.8 Runtime files

/run/<service>/

Use:

Examples:

/run/nginx.pid
/run/sshd.pid
/run/miapp/

16.9 tmpfiles.d

/etc/tmpfiles.d/
/usr/lib/tmpfiles.d/
/run/tmpfiles.d/

Use:

Example file:

/etc/tmpfiles.d/miapp.conf

Contents:

d /run/miapp 0750 miapp miapp -
d /var/log/miapp 0750 miapp miapp -

Apply manually:

Terminal window
sudo systemd-tmpfiles --create /etc/tmpfiles.d/miapp.conf

Explanation:


16.10 sysusers.d

/etc/sysusers.d/
/usr/lib/sysusers.d/
/run/sysusers.d/

Use:

Example:

/etc/sysusers.d/miapp.conf

Contents:

u miapp - "System user for MiApp" /var/lib/miapp /usr/sbin/nologin

Apply manually:

Terminal window
sudo systemd-sysusers /etc/sysusers.d/miapp.conf

Explanation:


When running:

Terminal window
sudo systemctl enable miapp.service

systemd may create symlinks such as:

/etc/systemd/system/multi-user.target.wants/miapp.service -> /etc/systemd/system/miapp.service

Explanation:


16.12 Common environment files

There is no single universal location, but these are common:

/etc/default/<service> # Debian/Ubuntu in some packages
/etc/sysconfig/<service> # RHEL/Fedora in some packages
/etc/<service>/<service>.env

Examples:

/etc/default/nginx
/etc/sysconfig/sshd
/etc/miapp/miapp.env

These files only affect the service if the unit file has a directive such as:

EnvironmentFile=/etc/miapp/miapp.env

Reference sources


Quick reference: cheat sheet of frequent commands

Terminal window
# Check status
systemctl status servicio.service
# Start now
sudo systemctl start servicio.service
# Stop now
sudo systemctl stop servicio.service
# Restart
sudo systemctl restart servicio.service
# Reload service configuration
sudo systemctl reload servicio.service
# Enable on boot
sudo systemctl enable servicio.service
# Enable and start now
sudo systemctl enable --now servicio.service
# Disable on boot
sudo systemctl disable servicio.service
# Disable and stop now
sudo systemctl disable --now servicio.service
# Mask to prevent starting
sudo systemctl mask servicio.service
# Unmask
sudo systemctl unmask servicio.service
# Reload unit definitions
sudo systemctl daemon-reload
# View logs
journalctl -u servicio.service
# View recent logs
journalctl -u servicio.service -n 100 --no-pager
# Follow logs in real time
journalctl -u servicio.service -f
# View failed units
systemctl --failed
# Clear failed state
sudo systemctl reset-failed servicio.service
# View effective unit file
systemctl cat servicio.service
# Create local override
sudo systemctl edit servicio.service
# Validate unit
systemd-analyze verify /etc/systemd/system/servicio.service

Share this post on:

Previous Post
How to convert a JPEG or PNG to ICO on the Linux CLI
Next Post
Easy graphics inclusion: Mermaid.