systemd-template
title: Eigener systemd-Service für Apps slug: systemd-service tags: [systemd, linux, services, howto] updated: 2025-10-16 summary: Eigene Applikation als systemd-Service betreiben: Unit-Datei, Restart-Policy, Status & Logs.
Eigener systemd-Service für Apps (Python, Node, Go, …)
Ziel: Eigene Anwendung als systemd-Service betreiben: Start beim Boot, automatischer Neustart bei Fehlern, Logs über
journalctl.Beispiele orientieren sich an Ubuntu Server (22.04/24.04), funktionieren aber sinngemäß auf allen Distributionen mit systemd.
Inhalt
- Überblick: Was ist ein systemd-Service?
- Beispiel-Unit für eine eigene App
- Service-Datei anlegen & aktivieren
- Status & Logs prüfen
- Wichtige Direktiven kurz erklärt
- Varianten (Environment-Datei, andere Pfade)
- Checkliste bei Problemen
Überblick: Was ist ein systemd-Service?
- systemd verwaltet Dienste über Unit-Dateien im INI-Format (
key=valuein Sektionen). - Ein Service besteht typischerweise aus den Sektionen
[Unit]→ Metadaten & Abhängigkeiten,
[Service]→ wie der Prozess gestartet wird,
[Install]→ wie der Dienst beim Booten „eingehängt“ wird. - Unit-Dateien werden als
*.servicegespeichert, z. B.meineapp.service.
Typische Pfade für System-Units
/etc/systemd/system→ eigene/überschreibende System-Dienste (Admin-Konfiguration)./usr/lib/systemd/systemoder/lib/systemd/system→ Dateien, die von Paketen installiert werden.
Für eigene Services reicht normalerweise: /etc/systemd/system.
Beispiel: Minimaler Service für /opt/myapp
Beispiel: Python-App, die als Benutzer
appuserunter/opt/myappläuft.
[Unit]
Description=Meine App
After=network.target
[Service]
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Platzhalter anpassen:
User=appuser→ unprivilegierter Benutzer, unter dem die App laufen soll.WorkingDirectory=/opt/myapp→ Ordner, in dem deine App liegt.ExecStart=...→ Befehl zum Starten deiner App (Python, Node, Binary, …).
Schritt 1 – Service-Datei unter /etc/systemd/system anlegen
sudo nano /etc/systemd/system/meineapp.service
- Inhalt aus dem Beispiel oben einfügen.
- Benutzer, Pfade, ExecStart an deine App anpassen.
- Datei speichern (
Strg+O,Enter) und Editor schließen (Strg+X).
Damit liegt die Unit-Datei an einem Pfad, den systemd standardmäßig einliest.
Schritt 2 – Dienst laden, aktivieren & starten
Nach dem Anlegen oder Ändern der Unit-Datei:
sudo systemctl daemon-reload
sudo systemctl enable --now meineapp
Was passiert hier technisch?
daemon-reloadliest die Unit-Dateien neu ein.enablelegt passende Symlinks an (z. B. untermulti-user.target.wants/), damit der Dienst beim Boot automatisch gestartet wird.--nowsorgt zusätzlich dafür, dass der Dienst direkt gestartet bzw. gestoppt wird (je nach Kommando).
Alternativ:
# nur aktivieren, aber jetzt noch nicht starten
sudo systemctl enable meineapp
# nur jetzt starten, ohne Autostart zu setzen
sudo systemctl start meineapp
Schritt 3 – Status & Logs des Dienstes prüfen
Status & letzte Logs in einem:
systemctl status meineapp
Typische Dinge, auf die du achten solltest:
- „Active: active (running)“ → Dienst läuft.
- „Active: failed“ → Startfehler, unten in der Ausgabe stehen die relevanten Zeilen.
Live-Logs verfolgen:
journalctl -u meineapp -f
-u meineapp→ nur Logs dieses Dienstes.-f→ „follow“ / Live-Ansicht (wietail -f).
Wichtige Direktiven im Beispiel erklärt
[Unit] Sektion
-
Description=
Kurze Beschreibung, die z. B. insystemctl statusangezeigt wird. -
After=network.target
Gibt die Startreihenfolge an: Der Dienst wird erst gestartet, nachdemnetwork.targeterreicht ist.
Hinweis:After=setzt primär eine Reihenfolge, es garantiert nicht, dass das Netzwerk schon komplett „fertig“ ist. Für harte Abhängigkeiten gibt esRequires=/Wants=.
[Service] Sektion
-
User=
Benutzer, als der der Dienst läuft. Für Web-/App-Dienste solltest du in der Regel nichtrootverwenden. -
WorkingDirectory=
Verzeichnis, in dem der Prozess gestartet wird. Praktisch, wenn dein Startbefehl relative Pfade nutzt. -
ExecStart=
Voller Befehl zum Starten deiner App (mit absolutem Pfad zum Interpreter bzw. Binary).
Beispiele:
/usr/bin/python3 /opt/myapp/app.py
/usr/bin/node /opt/myapp/server.js
/opt/myapp/myapp-binary
-
Restart=on-failure
Dienst wird automatisch neu gestartet, wenn der Prozess mit Fehlercode endet (nicht bei normalem Exit). -
RestartSec=5
Wartezeit in Sekunden, bevor systemd einen Neustart versucht.
[Install] Sektion
WantedBy=multi-user.target
Sorgt dafür, dasssystemctl enable meineappeinen Symlink inmulti-user.target.wants/erstellt.
Ergebnis: Der Dienst startet im normalen Multi-User-Modus automatisch mit.
Varianten & sinnvolle Erweiterungen
Environment-Datei nutzen
Konfiguration sauber von der Unit-Datei trennen:
- Environment-Datei anlegen:
sudo nano /etc/default/meineapp
Beispielinhalt:
APP_ENV=production
APP_PORT=8080
- Service-Datei erweitern:
[Service]
User=appuser
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/default/meineapp
ExecStart=/usr/bin/python3 /opt/myapp/app.py
Restart=on-failure
RestartSec=5
In deiner App kannst du dann APP_ENV / APP_PORT auslesen (z. B. über Umgebungsvariablen).
Nach Änderungen:
sudo systemctl daemon-reload
sudo systemctl restart meineapp
Andere Pfade für Unit-Dateien
- Eigene Services / Overrides:
/etc/systemd/system/*.service - Von Paketen gelieferte Units:
/usr/lib/systemd/system/*.serviceoder/lib/systemd/system/*.service`
Empfehlung: Eigene Dienste und Anpassungen immer unter /etc/systemd/system halten, damit Paket-Updates deine Konfiguration nicht überschreiben.
Checkliste / Troubleshooting für systemd-Services
Konfiguration prüfen
sudo systemctl daemon-reload
Service manuell steuern
sudo systemctl start meineapp
sudo systemctl stop meineapp
sudo systemctl restart meineapp
Status & letzte Logs
systemctl status meineapp
journalctl -u meineapp -n 50 --no-pager
Start beim Booten checken
systemctl is-enabled meineapp
systemctl list-unit-files 'meineapp*'
Wirksame Unit-Definition anzeigen
systemctl cat meineapp
Typische Fehlerquellen
- Pfade in
ExecStartfalsch oder Binary nicht ausführbar. WorkingDirectoryexistiert nicht oder hat falsche Rechte.- Benutzer in
User=hat keinen Zugriff auf Dateien/Ports. - Fehlende/kaputte Environment-Datei (
EnvironmentFile=zeigt ins Leere). daemon-reloadnach Änderungen vergessen → systemd nutzt noch die alte Version.
Wenn der Dienst zwar startet, aber sofort wieder stirbt:
journalctl -u meineapp -b
durchgehen und die eigentliche Exception/Fehlermeldung suchen.