Stage 3 · Build
systemd Service Management & Resource Control
Unit Dependencies & Ordering
Wants, Requires, After, Before, PartOf, and failure propagation across targets.
Dependency Types
| Directive | Strength | Behavior |
|---|---|---|
| Requires | Strong | If dependency fails, this unit fails too |
| Wants | Weak | Try to start dependency, but don't fail |
| BindsTo | Stronger | Stop if dependency stops or becomes inactive |
| PartOf | Weak | Restart/stop with dependency |
| Conflicts | Inverse | Cannot run simultaneously |
| Upholds | Strong | Keep dependency running |
# Strong dependency (fail if postgresql fails)
[Unit]
Requires=postgresql.service
After=postgresql.service
# Weak dependency (try to start, don't fail)
[Unit]
Wants=redis.service
After=redis.service
# BindsTo (stop if dependency stops)
[Unit]
BindsTo=network-online.target
After=network-online.target
# PartOf (restart with dependency)
[Unit]
PartOf=myapp.service
# If myapp restarts, this unit restarts too
# Conflicts (cannot run at same time)
[Unit]
Conflicts=nginx.service
# Cannot run nginx and this service simultaneouslyRequires + After is the most common pattern for mandatory dependencies. Wants + After is used for optional dependencies.
Ordering Directives
# After: Start this unit after the specified unit
[Unit]
After=postgresql.service redis.service
# Start postgresql and redis first, then start this unit
# Before: Start this unit before the specified unit
[Unit]
Before=nginx.service
# Start this unit before nginx
# After + Requires = start dependency, wait, then start this
# After + Wants = try to start dependency, then start this
# After alone = start in parallel, but this waits for dependency
# Ordering without dependency
[Unit]
After=network-online.target
# No Requires/Wants — just ordering
# This unit starts after network, regardless of network statusAfter/Before only control ordering, not dependency. You need Requires/Wants to create actual dependencies. After without Requires means 'start in parallel, but wait'.
Failure Propagation
# Failure propagation rules:
# Requires: dependency fails -> this unit fails
# Wants: dependency fails -> this unit still starts
# BindsTo: dependency stops -> this unit stops
# PartOf: dependency fails -> this unit is not affected
# Configure failure behavior
[Service]
Restart=on-failure # Restart this unit on failure
RestartSec=5
# Failure action (run command on failure)
[Service]
ExecStopPost=/usr/bin/notify-failure.sh
# In [Unit] section
OnFailure=emergency-notify.service
# Start emergency-notify.service if this unit fails
# Target failure propagation
# If a RequiredBy target fails, dependent services may fail
# If a WantedBy target fails, dependent services continueFailure propagation is complex. Requires propagates failure, Wants does not. OnFailure runs a specific unit when this unit fails.
Target Dependencies
# Targets group units and define system states
# multi-user.target dependencies
systemctl list-dependencies multi-user.target
# multi-user.target
# ├─sshd.service
# ├─nginx.service
# ├─postgresql.service
# └─...
# Add a service to a target
# In the service [Install] section:
[Install]
WantedBy=multi-user.target
# This means: when multi-user.target starts, start this service
# Custom target
# /etc/systemd/system/myapp.target
[Unit]
Description=MyApp Stack
Requires=myapp.service postgresql.service redis.service
After=network.target
[Install]
WantedBy=multi-user.target
# Enable services in custom target
# myapp.service:
[Install]
WantedBy=myapp.targetTargets group related services. multi-user.target is the main server state. Create custom targets to group application services.
Conflict Management
# Conflicts prevents simultaneous execution
[Unit]
Conflicts=nginx.service
# If nginx is running, this unit cannot start
# If this unit is running, nginx cannot start
# Use cases:
# - Alternative implementations (nginx vs apache)
# - Exclusive access to a resource
# - Maintenance mode vs normal operation
# Example: maintenance mode
# /etc/systemd/system/maintenance.service
[Unit]
Conflicts=production.service
[Service]
Type=oneshot
ExecStart=/usr/bin/enter-maintenance.sh
# When maintenance.service starts, production.service stops
# When production.service starts, maintenance.service stopsConflicts creates mutual exclusion. Starting one unit automatically stops the conflicting unit.
Inspecting Dependencies
# Full dependency tree
systemctl list-dependencies nginx.service
# Reverse dependencies (what depends on this)
systemctl list-dependencies --reverse nginx.service
# All dependencies
systemctl list-dependencies --all nginx.service
# After ordering
systemctl list-dependencies --after nginx.service
# Before ordering
systemctl list-dependencies --before nginx.service
# Analyze boot dependencies
systemd-analyze dot multi-user.target | dot -Tpng > boot-deps.png
# Check unit file dependencies
systemctl show nginx.service -p Requires,Wants,BindsTo,After,Before
# Verify all dependencies exist
systemd-analyze verify /etc/systemd/system/myapp.servicesystemctl list-dependencies shows the full dependency tree. --reverse shows what depends on a unit. Use this to understand impact of changing a service.
Requires causes hard failures. Wants is more resilient — if the dependency fails, the service still starts. Use Requires only for truly critical dependencies.
After=postgresql.service without Requires/Wants means 'start in parallel, but this unit waits for postgresql'. If postgresql fails, this unit still starts.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.