How to Write a systemd Service Unit File

A systemd unit file has three sections and about eight directives that matter for production. This guide walks through each one - what it does, why it is there, and how to validate the file without touching a running system.

DevOps Engineersystemdlinuxservice-management

The three sections every unit needs

A service unit lives in a .service file. It always has three sections: [Unit] for metadata and ordering, [Service] for how to run the process, and [Install] for when to start it on boot.

Here is a complete, production-ready example for a Python Flask API:

[Unit]
Description=Production Flask API
After=network.target

[Service]
Type=simple
User=appuser
ExecStart=/opt/venv/bin/python /opt/api/app.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

[Unit] - metadata and ordering

[Service] - the process spec

[Install] - boot integration

WantedBy=multi-user.target is the correct target for almost every server service. It means "enable this unit when the system boots into the normal multi-user runlevel." After writing the file, enable and start it:

systemctl enable --now api.service

--now enables (creates the symlink) and starts the service in one shot.

Validate before you deploy

systemd-analyze verify checks syntax and required fields without starting the service or needing PID 1 running:

systemd-analyze verify api.service

A clean file exits with no output. Any warning or error is printed to stderr. Fix them before copying the file to /etc/systemd/system/.

Common production additions

Once the basics pass, harden the unit with resource and security directives:

[Service]
MemoryMax=512M
CPUQuota=50%
NoNewPrivileges=true
EnvironmentFile=/etc/api.env

EnvironmentFile keeps secrets out of the unit file itself - write KEY=VALUE pairs to /etc/api.env (mode 0600, owned by root) and systemd injects them as environment variables at start time.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

What are the three sections of a systemd service unit file?

[Unit] holds the description and ordering (e.g. After=network.target). [Service] defines how to run the process - ExecStart, Type, User, Restart. [Install] sets when it starts on boot (WantedBy=multi-user.target).

How do I validate a systemd unit file without restarting the system?

Run systemd-analyze verify <unit-file>. It checks syntax and required fields locally - no running systemd PID 1 needed. A clean file produces no output; errors and warnings are printed to stderr.

What is the difference between Type=simple and Type=forking?

Use Type=simple when the process systemd launches stays in the foreground - Python, Node.js, gunicorn, uvicorn all do this. Use Type=forking only for old-style daemons that double-fork into the background on startup.

Keep learning

Fix the Nginx 502 Bad GatewayDevOps projectRecover a Crashed Linux ServiceDevOps projectCorrect a Postgres Port MismatchDevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →