systemd Service Config - CodeSwordsman

Practical snippets from writing a service unit to enabling, logging, timers and drop-in overrides.

systemd 245+Updated 2026-10-2931 commands

Service Unit Basics

A complete, copy-ready service unit template

[Unit]
Description=My App
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/opt/my-app
EnvironmentFile=-/etc/my-app/env
ExecStart=/opt/my-app/bin/server --port 8080
Restart=always
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

Run daemon-reload after any unit change, or it is ignored.

Keep env vars in a file instead of hardcoding them

# /etc/my-app/env
NODE_ENV=production
PORT=8080

A leading - makes a missing file non-fatal.

Use simple for foreground programs; add exec inside scripts

Type=simple
ExecStart=/opt/my-app/bin/server

Use forking only for programs that daemonize themselves.

Common Directives

Validate prerequisites before start; failure aborts it

ExecStartPre=/usr/bin/test -f /etc/my-app/config.yaml

Set the working directory used for relative paths

WorkingDirectory=/opt/my-app

Run the service as a non-root user and group

User=deploy
Group=deploy

Declare a single environment variable inline

Environment=NODE_ENV=production

Switch to EnvironmentFile when there are many variables.

Restart automatically after failures with a 3s delay

Restart=always
RestartSec=3

A bad config restarts forever; check status first.

Raise the file descriptor limit for high-concurrency services

LimitNOFILE=65535

Wrap in sh -c when you need pipes or redirection

ExecStart=/bin/sh -c 'cat /etc/my-app/list | xargs echo'

A bare pipe is passed as an argument, not executed.

Enable & Reload

Reload unit files after editing them

sudo systemctl daemon-reload

It does not restart the process; follow with restart.

Enable at boot and start the service right away

sudo systemctl enable --now my-app

Check the status and recent log lines

sudo systemctl status my-app

Restart the service, dropping current connections

sudo systemctl restart my-app

Check whether the service is enabled at boot

systemctl is-enabled my-app

Disable at boot and stop the service now

sudo systemctl disable --now my-app

Logs

Follow the log of a specific service

journalctl -u my-app -f

Show only the last ten minutes of logs

journalctl -u my-app --since "10 min ago"

Strip metadata and output message text only

journalctl -u my-app -o cat -n 200

Show only error-level logs from the current boot

journalctl -u my-app -p err -b
Risky

Keep 7 days of logs and permanently delete the rest

sudo journalctl --vacuum-time=7d

Check usage with journalctl --disk-usage before running.

Timers

The task unit triggered by the timer, using oneshot

[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh

Run daily at 03:00; Persistent catches up after downtime

[Unit]
Description=Run backup every night

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
Unit=backup.service

[Install]
WantedBy=timers.target

Enable the .timer unit, not the .service.

List timers and their next trigger time

systemctl list-timers --all

Enable the timer and register it immediately

sudo systemctl enable --now backup.timer

Validate a calendar expression and show the next run

systemd-analyze calendar "*-*-* 03:00:00"

Override & Debug

Create a drop-in override without touching the original unit

sudo systemctl edit my-app

The override lands in /etc/systemd/system/my-app.service.d/.

Show the effective unit plus all overrides

systemctl cat my-app

Statically verify unit syntax and referenced paths

systemd-analyze verify /etc/systemd/system/my-app.service

Errors usually mean a missing ExecStart path or dependency.

Show recent system-wide errors and hints

journalctl -xe

List service units that failed to start

systemctl --failed

Related tools

This website uses cookies to ensure you get the best experience on our website. Privacy Policy.