Kaum eine Software verwende ich so lange wie TeamDrive. Die ersten Artikel dazu in diesem Blog stammen bereits aus dem Jahr 2011 [0], [1].
Nachdem ich den TeamDrive Personal Server schon auf einem NAS installiert und als Dienst konfiguriert habe, dokumentiere ich in diesem Artikel die Erstellung einer Systemd-Service-Unit. Dazu sei gesagt, dass ich kein Experte für Systemd-Units bin. Tatsächlich kenne ich mich nichtmal besonders gut damit aus. Folgende Lösung funktioniert auf meinem Server. Anregungen zur Verbesserung der Service-Unit nehme ich gern in den Kommentaren entgegen.
Installation des TeamDrive Personal Server
Zuerst muss der TeamDrive Personal Server heruntergeladen und installiert werden. Dabei hilft das dazugehörige Handbuch. Auch wenn dieses schon einige Jahre auf dem Buckel hat, sind die enthaltenen Informationen weiterhin aktuell.
Da die Installation hier im Blog bereits einmal beschrieben wurde, gehe ich hier im Detail nicht weiter darauf ein. Im vorliegenden Fall wurde die Software im Verzeichnis /opt/tdps installiert. Darüber hinaus wurde ein Benutzer tdps erstellt, welchem das Verzeichnis /opt/tdps und die darin enthaltenen Dateien gehören.
Systemd-Service-Unit tdps.service
Ich habe den TeamDrive Personal Server (TDPS) auf einem Debian 10 System installiert. Um diesen wie alle übrigen Dienste mit dem Programm systemctl verwalten zu können, habe ich die Datei /etc/systemd/system/tdps.service mit folgendem Inhalt erstellt:
[Unit]
Description="TeamDrive Personal Server"
After=network.target
[Service]
User=tdps
PIDFile=/opt/tdps/tdpsd.pid
ExecStart=/opt/tdps/tdpsd -c /opt/tdps/tdps.config -m /opt/tdps/mime.types -w /opt/tdps
ExecStop=/opt/tdps/stop-tdps -p /opt/tdps/tdpsd.pid
KillMode=process
PrivateTmp=yes
ProtectHome=yes
ProtectSystem=full
[Install]
WantedBy=multi-user.target
Im Abschnitt [Unit]
findet sich eine kurze Beschreibung der Service-Unit. Die Option After=network.target
gibt an, dass diese Unit erst gestartet werden soll, wenn das Netzwerk zur Verfügung steht. Dies ist Voraussetzung, um den Dienst über das Netzwerk nutzen zu können.
Die Zeile im letzten Abschnitt [Install]
definiert, dass diese Unit Bestandteil des multi-user.target
ist und mit diesem geladen wird.
Der Abschnitt [Service]
definiert die für den Dienst relevanten Parameter. Die gewählten Optionen werde ich im Folgenden erläutern.
User=
gibt den Namen des Benutzers an, mit dessen Rechten der Dienst ausgeführt werden soll. In diesem Fall wird der extra für diesen Zweck erstellte User tdps verwendet.
PIDFile=
gibt den Pfad an, wo der Dienst seine PID speichert. Der Service-Manager liest die PID des Hauptprozess aus dieser Datei, nachdem der Service gestartet wurde.
ExecStart=
gibt das Kommando mit allen notwendigen Argumenten an, um den Dienst zu starten. Ich habe hier ein wenig mit verschiedenen Aufrufen experimentiert. Dabei habe ich verschiedene Möglichkeiten gefunden, den Dienst erfolgreich zu starten. Worin die Unterschiede im Aufruf genau bestehen, kann ich leider nicht sagen. Am Ende habe ich mich für obige Kommandozeile entschieden, die ich im TeamDrive-Forum gefunden habe. Aus diesem Foren-Beitrag habe ich auch Stumpf die Option KillMode=process
übernommen. Zur Option selbst kann ich (noch) nicht viel sagen. Dies änderst sich vielleicht noch, da ich mich noch etwas damit beschäftigen möchte.
Mit ExecStop=
gibt man entsprechend an, wie der Dienst zu stoppen ist. Auch hier stammt die Kommandozeile aus oben verlinktem Foren-Thread.
Die nächsten drei Optionen
, PrivateTmp=
ProtectHome=
und ProtectSystem=
dienen dazu den Dienst zu härten. Durch PrivateTmp=yes
erhält der gestartete Prozess einen eigenen Dateisystem-Namespace für /tmp und /var/tmp. So kann der Prozess nicht auf die Dateien anderer Prozesse und Benutzer in den normalen Verzeichnissen /tmp und /var/tmp zugreifen. Mit ProtectHome=yes
wird der Zugriff des Dienstes auf die Verzeichnisse /home, /root und /run/user verhindert. ProtectSystem=full
sorgt dafür, dass die Verzeichnisse /boot, /etc und /usr im Nur-Lese-Modus für den Prozess zur Verfügung stehen. Damit ist sichergestellt, dass der von dieser Unit gestartete Prozess keine Dateien innerhalb dieser Verzeichnisse verändern kann.
Die drei im vorhergehenden Abschnitt genannten Optionen stellen einen zusätzlichen Schutz dar. Zwar darf der Benutzer tdps schon aufgrund der Datei- und Verzeichnisberechtigungen nicht in den genannten Verzeichnissen schreiben und Dateien verändern bzw. diese überhaupt lesen, doch bieten diese Optionen einen zusätzlichen Schutz und greifen auch noch, wenn jemand Schindluder mit den Berechtigungen getrieben hat. Daher halte ich es für sinnvoll diese Optionen wenn möglich in allen Service-Units zu nutzen.
Neben den drei hier vorgestellten Optionen gibt es noch einige weitere, welche im englischsprachigen Artikel „Mastering systemd: Securing and sandboxing applications and services“ nachgelesen werden können. Ich finde diese so sinnvoll, dass ich mich ehrlich gesagt frage, warum die genannten Einstellungen nicht der Standard sind und man diese editieren muss, wenn man entsprechende Zugriffe explizit erlauben möchte.
Damit ist alles getan und dokumentiert. Der TDPS lässt sich mit oben beschriebener Service-Unit starten und stoppen. Den Status abfragen kann man selbstverständlich auch.
Es bleibt ein kleiner Schönheitsfehler. Wird der Dienst mittels sudo systemctl stop tdps.service
gestoppt, endet die Unit im Status „failed“. Warum das so ist, habe ich noch nicht herausgefunden. Ich vermute, es hängt damit zusammen, dass der Dienst mittels SIGTERM beendet wird. Bin mir an dieser Stelle jedoch nicht sicher. Falls von euch jemand eine Idee dazu hat, freue ich mich über euren Kommentar.
Wie schreibt ihr eure Service-Units? Welche Optionen sollten eurer Meinung nach in keiner Unit fehlen? Wenn ihr mögt, lasst uns gerne in den Kommentaren darüber diskutieren.