What is a unit file?¶
A systemd unit file is a plain-text configuration file that tells systemd how to manage a process. Service units end in .service and live in one of these directories:
/etc/systemd/system/ # admin-created (highest priority)
/usr/lib/systemd/system/ # vendor-provided by packages
/run/systemd/system/ # runtime units (not persistent)
Anatomy of a service unit¶
[Unit]
Description=My Application
Documentation=https://example.com/docs
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server --port 8080
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Key directives¶
[Unit] section:
- After= — start this unit after these others are active
- Requires= — hard dependency; fails if dependency fails
- Wants= — soft dependency; continues even if dependency fails
[Service] section:
- Type=simple — default; ExecStart process is the main process
- Type=forking — process forks; systemd tracks the PID file
- Type=notify — process sends sd_notify() when ready
- Type=oneshot — runs once and exits (use with RemainAfterExit=yes)
- ExecStartPre= — run before ExecStart
- ExecStartPost= — run after ExecStart succeeds
- Restart=on-failure — restart if exit code is non-zero or killed by signal
Enable and start a service¶
# Copy unit file (if not in /etc/systemd/system/ already)
sudo cp myapp.service /etc/systemd/system/
# Reload systemd to pick up the new file
sudo systemctl daemon-reload
# Enable (creates symlink so it starts at boot)
sudo systemctl enable myapp.service
# Start now
sudo systemctl start myapp.service
# Enable and start in one command
sudo systemctl enable --now myapp.service
Check status¶
systemctl status myapp.service
# ● myapp.service - My Application
# Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
# Active: active (running) since Fri 2026-05-25 09:00:00 UTC; 2h ago
# Main PID: 1234 (server)
Read logs with journalctl¶
# All logs for the service
journalctl -u myapp.service
# Follow live output
journalctl -u myapp.service -f
# Since last boot
journalctl -u myapp.service -b
# Last 50 lines
journalctl -u myapp.service -n 50
# Since a specific time
journalctl -u myapp.service --since "2026-05-25 08:00"
Diagnose a failed service¶
# 1. Check status and last error
systemctl status myapp.service
# 2. Read full journal for context
journalctl -u myapp.service --no-pager -n 100
# 3. Test the ExecStart command manually
sudo -u myapp /opt/myapp/bin/server --port 8080
# 4. Check if the binary exists and is executable
ls -l /opt/myapp/bin/server
Common patterns¶
# Override a vendor unit without editing it directly
sudo systemctl edit nginx.service
# Creates /etc/systemd/system/nginx.service.d/override.conf
# List all failed units
systemctl --failed
# Stop and disable (survives reboots)
sudo systemctl disable --now myapp.service
# Mask (prevents any start, even manual)
sudo systemctl mask myapp.service
Key takeaways¶
- Place custom unit files in
/etc/systemd/system/— never edit vendor files in/usr/lib/systemd/system/. - Always run
systemctl daemon-reloadafter adding or modifying unit files. Restart=on-failurewithRestartSec=5sis the safe default for long-running services.journalctl -u <service> -fis your first tool when something goes wrong.