tutorial

systemd Services on Embedded Linux

· beginner · 50 min

From "works when I run it" to "runs forever on its own": service files, restart policies, dependencies, logging, and timers for applications that run unattended.

hardware
Raspberry Pi 5
os
Raspberry Pi OS Bookworm
verified

before you start

  • Comfortable with the Linux shell
  • A Linux machine running systemd (Raspberry Pi OS, Ubuntu, Debian, Fedora, and most others)
  • Python 3 for the Python examples, Node.js 18+ for the Node.js example

full source: github.com/ranaweerasupun/resources-tools/tree/main/systemd/examples

May it be a sensor pipeline, an MQTT client or a web server you have engineered something that works perfectly. And then on one day, the device loses power or you reboot it. You get the device powered again but there is only silence. Your MQTT client or the webserver doesn’t start. You curse, SSH in, run your script manually, and it all comes back to life. “Well, this is eveyday life!” you say. But it doesn’t have to be. You just need to learn how to laverage systemd to make them run at boot.

That gap between “works when I run it” and “runs automatically and reliably forever” is exactly what systemd fills.

What you will learn in this short tutorial

How systemd fits into the Linux boot process, how to write a service file from scratch, how to make services restart themselves after crashes, how to declare dependencies so things start in the right order, how to manage configuration and secrets through environment files, how to read and filter service logs, and how to replace cron jobs with systemd timers.

Work through the pages in order if you’re new to systemd. If you have some experience, jump to the section you need.

Quick start

If you just want to get a Python script running as a service as fast as possible, create the service file:

sudo nano /etc/systemd/system/my-app.service
[Unit]
Description=My Application
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/my-app
ExecStart=/usr/bin/python3 /home/pi/my-app/main.py
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Then enable and start it:

sudo systemctl daemon-reload
sudo systemctl enable my-app.service
sudo systemctl start my-app.service

And check that it’s running:

sudo systemctl status my-app.service

Ready-to-use examples

I have written some examples and put the my github. Every example service file and application script are in the examples/ folder on GitHub: a Python service, a Node.js service, a service that loads secrets from an environment file, and a systemd timer that runs a script on a schedule.

I have use a Raspberry Pi but these are not just for the Pi

Every concept here works on any modern Linux distribution that uses systemd, which is virtually all of them. The examples use User=pi and paths like /home/pi/ because the Pi is what I have tested them on. But substituting your own username and paths works identically on Ubuntu, Debian, Fedora, or any other systemd-based distro.

Comments