systemd Service Units: Anatomy of a Unit File

Service units are where systemd behavior becomes explicit. If you can read [Unit], [Service], and [Install] sections confidently, you can diagnose and tune most service behavior.

Table of Contents

This post explains how service units are structured and how to change behavior safely.

Unit File Anatomy

Operational Patterns

Series Navigation

Unit file anatomy

A typical service unit has three sections.

[Unit]
Description=Example API service
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=app
Group=app
WorkingDirectory=/opt/example-api
Environment=PORT=8080
ExecStart=/opt/example-api/bin/server
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Section role summary

Think about sections this way:

  • [Unit] defines dependency and ordering relationships
  • [Service] defines how the process runs and recovers
  • [Install] defines how the unit is linked into startup targets

Directive deep dive

The most important directives to master early:

  • Description gives human-readable context in status output
  • After and Before control ordering but not requirement
  • Wants and Requires declare relationship strength
  • Type declares startup semantics such as simple, forking, oneshot, and notify
  • ExecStart is the primary command systemd executes
  • ExecReload defines reload behavior when the daemon supports it
  • User and Group avoid running daemons as root unless required
  • WorkingDirectory sets execution context for relative paths
  • Environment and EnvironmentFile inject runtime settings
  • Restart and RestartSec define failure recovery policy
  • WantedBy controls install-time target linkage

Read existing units first

Before writing a new unit, inspect how packaged services are implemented on your host.

systemctl cat sshd.service
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths

This gives you examples of directives that match your distribution conventions.

Use drop-in overrides

Do not edit packaged files under /usr/lib/systemd/system directly because package updates may overwrite changes. Use a drop-in override under /etc/systemd/system.

sudo systemctl edit nginx.service

That command creates or edits:

/etc/systemd/system/nginx.service.d/override.conf

Example override:

[Service]
Restart=always
RestartSec=3s
Environment=NGINX_WORKERS=4

Reload and apply changes

After creating or editing units, refresh systemd metadata, then apply runtime changes.

sudo systemctl daemon-reload
sudo systemctl restart nginx.service
systemctl status nginx.service

daemon-reload is required for definition changes, while restart or reload applies behavior to the running process.

Reload vs restart

Pick the right action based on service capabilities and change scope:

  • Use reload when config changes are reloadable and downtime must be minimized
  • Use restart when binaries, startup parameters, or non-reloadable settings changed
  • Confirm the right choice in service docs because some units define ExecReload while others do not

Series navigation

With service units covered, the next topic is how system states and boot paths are modeled through targets and dependency semantics.

Next in this series

Next, we map SysV runlevels to systemd targets and break down dependency rules that shape boot order.

systemd Targets and Boot Dependencies: From Runlevels to multi-user.target