- Deptool ist ein Deployment-Werkzeug, das entwickelt wurde, um DNS- und Webserver-Konfigurationen selbst zu betreiben. Es zeigt zunächst einen Plan der Änderungen an und wendet sie nach Bestätigung auf die Ziel-Hosts an.
- Es rendert die gesamte Cluster-Konfiguration im Voraus, verwaltet sie mit Git und legt unter
/var/lib/deptool pro Commit ein Verzeichnis auf jedem Host an. Anschließend wird durch Umstellen des symbolischen Links current atomar auf eine andere Version gewechselt.
- Vor dem Deployment wird auf jedem Host ein Lock gesetzt und der lokal bekannte Commit mit dem tatsächlich deployten Zustand verglichen; bei einem veralteten Plan wird abgebrochen. Das Deployment läuft nur weiter, wenn Locks für alle betroffenen Hosts gesichert wurden.
- Services laufen als systemd-Units und werden bei Konfigurationsänderungen neu gestartet. Falls der Start fehlschlägt, wird der Link auf die vorherige bekannte funktionierende Version zurückgesetzt und der Dienst erneut gestartet, sodass ein automatischer Rollback im Millisekundenbereich erfolgt.
- Die Remote-Ausführung verwendet SSH nur als Transportebene in einem statischen Agent-Modell, sodass eine automatische Installation allein mit coreutils selbst in Umgebungen wie Flatcar Linux ohne Python und Paketmanager möglich ist.
Warum Deptool entstanden ist
- Ausgangspunkt war der Umzug des Blogs nach Europa, um den Widerspruch zu vermeiden, Texte über europäische digitale Souveränität auf US-Hosting und von den USA kontrollierten Hyperscalern zu veröffentlichen.
- Da auch DNS von Cloudflare abhing, entstand die Notwendigkeit, DNS-Server selbst zu betreiben.
- Der bisherige Webserver lief auf einer kleinen VM mit Nginx und Lego für die Zertifikatserneuerung; die Nginx-Konfiguration wurde mit Nix erzeugt und dann per kleinem Python-Skript auf den Server kopiert, gefolgt von einem Nginx-Neustart.
- Für den Betrieb von DNS-Servern wären jedoch mindestens zwei Server, mehr systemd-Units, Konfigurationsdateien und Zonefiles nötig gewesen, sodass die bisherigen Skripte nicht mehr ausreichten.
- Ein Umstieg auf NixOS wäre eine Option gewesen, stattdessen sollte aber der bestehende Ansatz mit minimalem Basis-OS und Services in schreibgeschütztem chroot mit nur den nötigen Binärdateien beibehalten und dafür ein neues Deployment-Werkzeug gebaut werden.
Wie sich Deptool benutzt
- Deptool zeigt zuerst einen Plan für Änderungen an der Cluster-Konfiguration an und wendet diese nach Bestätigung auf die Ziel-Hosts an.
- Im Beispiel für ein DNS-Record-Update zeigt
deptool deploy an, dass auf s4.ruuda.nl und s5.ruuda.nl die nsd-Konfigurationsdatei geändert und nsd.service neu gestartet wird.
- Bei einem fehlgeschlagenen Deployment greift automatischer Rollback; im Beispiel wird nach einer Bestätigung für die 2 Hosts des
prod-Clusters in nur 0,99 Sekunden erfolgreich deployt.
- Die Ausgabe trennt Ziel-Hosts, betroffene Anwendungen, geänderte Dateien und neu zu startende systemd-Units, sodass vor dem Deployment sichtbar ist, was tatsächlich ausgeführt wird.
Anforderungen an das gewünschte Deployment-Werkzeug
-
Schnell
- Konfigurations-Updates sollen unter 1 Sekunde dauern; selbst ein Transatlantik-Ping liegt bei etwa 100 ms, daher gibt es aus Sicht des Autors keinen grundsätzlichen Grund, warum es wesentlich langsamer sein müsste.
-
Vorhersehbar
- Das Werkzeug soll zuerst zeigen, was es tun wird, und genau das dann ausführen.
- Gewünscht ist ein Modell mit getrennten Plan- und Apply-Schritten wie bei OpenTofu.
- Der Check-Mode von Ansible gilt als wenig vertrauenswürdig, weil sich Kettenreaktionen von Änderungen erst nach Ausführung imperativer Schritte zeigen können und sich Host-Zustände zwischen Check und echter Ausführung ändern können.
-
Sicher
- Selbst wenn eine Nginx-Konfiguration kaputt ist, soll der Webserver nicht für mehrere Minuten ausfallen; das Werkzeug muss daher automatische Rollbacks im Millisekundenbereich beherrschen.
-
Einfach
- Im Kern geht es nur darum, Konfigurationsdateien vom Laptop auf den Server zu kopieren und einige systemd-Units neu zu starten.
- Es muss nicht jedes Deployment-Problem lösen und auch keinen Kontrollfluss oder die Ausführung beliebigen Codes anbieten.
- Das Verarbeiten von Konfigurations-Templates kann ein separates Werkzeug übernehmen; die Kritik an YAML-Templating ist in generate und in einem separaten Werkzeug zur Dateigenerierung ausgelagert.
-
Deklarativ
- Wenn Dateien oder Anwendungen aus der Konfiguration entfernt werden, sollen sie auch auf dem Server entfernt werden.
- Es soll kein expliziter Cleanup-Schritt nötig sein, der sonst vergessen werden könnte und zu Drift oder liegen gebliebenen Dateien führt.
-
Keine anfängliche Einrichtung
- Server sollen direkt nach dem Provisioning verwaltet werden können.
- Wenn Agenten, Daemons, Abhängigkeiten oder eine Host-Registrierung manuell eingerichtet werden müssten, entstünde sofort wieder das Problem, auch diesen Prozess automatisieren zu müssen.
Trennung von Konfigurationsgenerierung und Deployment
- Die zentrale Idee ist die Trennung von Konfigurationsgenerierung und Deployment.
- Unsible, das David bei der Arbeit gebaut hat, führt Ansible-Playbooks nicht schrittweise aus, sondern erstellt lokal ein Tarball und sendet dieses an Hosts, um dort Dateien abzulegen.
- Auch die bisherigen einfachen Deployment-Skripte bauten Konfigurationen extern und überließen dem Skript weitgehend nur das Kopieren der Dateien.
- NixOS lässt sich als Anwendung derselben Idee auf das lokale System verstehen; von Nix lässt sich lernen, generierte Artefakte an Orten abzulegen, an denen mehrere Versionen nebeneinander existieren können, und den imperativen Teil der Systemadministration auf einen kleinen Aktivierungsschritt zu begrenzen, bei dem nur einige symbolische Links umgestellt werden.
- Dieses Design eignet sich sowohl für Paketverwaltung als auch für Systemkonfiguration.
Wie Deptool funktioniert
-
Die gesamte Cluster-Konfiguration wird im Voraus gerendert
- Die Konfigurationsdateien des gesamten Clusters werden vorab erzeugt und in einem Verzeichnis auf der Festplatte gespeichert.
- Der Verzeichnisbaum ist zwei Ebenen tief: ganz oben Verzeichnisse pro Ziel-Host, darunter Verzeichnisse pro Anwendung.
-
Ablage in einem Git-Repository
- Wenn das Konfigurationsverzeichnis in einem Git-Repository liegt, lassen sich Unterschiede zwischen Versionen vergleichen und Änderungen über den gesamten Cluster hinweg nachvollziehen.
- Über diffstat wird sichtbar, welche Hosts betroffen sind und welche Apps sich geändert haben; außerdem lässt sich der exakte Diff jeder Konfigurationsdatei ansehen.
-
Materialisierung der Dateien in isolierten Host-Verzeichnissen
- Alle Dateien liegen unter
/var/lib/deptool, damit sie nicht mit anderen Komponenten interferieren.
- Für jeden zu deployenden Commit wird ein Verzeichnis angelegt, sodass mehrere Versionen gleichzeitig auf dem Datenträger existieren können.
- Der symbolische Link
current zeigt auf die deployte Version, wodurch sich Versionen atomar umschalten lassen.
- Gelöschte Dateien werden in der nächsten Version nicht mehr materialisiert, sodass keine Altlasten zurückbleiben.
- Wenn Anwendungen Dateien an bestimmten Orten erwarten, können an den benötigten Stellen im Dateisystem symbolische Links nach
/var/lib/deptool angelegt werden.
- Das Erzeugen und Löschen symbolischer Links ist zwar nicht atomar, aber nur beim Hinzufügen oder Entfernen von Links nötig, nicht bei Änderungen am Dateiinhalt.
- Wenn ein solcher symbolischer Link in einer späteren Deployment-Version nicht mehr enthalten ist, zeigt der Diff an, dass er gelöscht werden muss, sodass keine Dateien zurückbleiben.
-
Deployment-Zustand wird in Remote-Tracking-Refs festgehalten
- Auf dem Laptop des Operators wird verfolgt, welcher Commit auf welchem Host deployt ist.
- Der Deployment-Zustand ist keine Eigenschaft des gesamten Clusters, sondern eine Eigenschaft pro Host.
- Wenn eine Änderung einen bestimmten Host nicht betrifft, muss dort auch kein neuer Commit deployt werden.
- Mit diesen Informationen lässt sich der Cluster-Diff offline berechnen; genau dieser Diff wird zum Deployment-Plan und kann in Millisekunden angezeigt werden.
-
Vor dem Deployment werden Locks auf den Ziel-Hosts erworben
- Per SSH wird eine Lock-Anfrage gesendet, die den Commit enthält, von dem lokal angenommen wird, dass er auf dem Host deployt ist.
- Wenn der Lock erworben wird, war der Plan gültig, und bis zur Freigabe des Locks kann kein anderes Deployment auf diesem Host stattfinden, sodass der Plan gültig bleibt.
- Ein Deployment wird nur ausgeführt, wenn Locks auf allen von der Änderung betroffenen Hosts gehalten werden.
- Wenn die Ref veraltet ist und inzwischen etwas anderes auf den Host deployt wurde, gilt der Plan als stale und wird abgebrochen.
- Nach dem Aktualisieren der lokalen Ref zeigt der nächste Lauf dann wieder den aktuellen Plan.
-
Neustart von systemd-Units
- Alle Services laufen als systemd-Units und starten schnell; im Zweifel wird daher lieber neu gestartet.
- Wenn sich die Konfiguration einer Anwendung ändert, werden die betroffenen systemd-Units neu gestartet.
- Wenn der Start einer Unit fehlschlägt, wird der symbolische Link auf die zuvor bekannte funktionierende Version zurückgesetzt und erneut gestartet, was automatische Rollbacks im Millisekundenbereich ermöglicht.
Modell optimistischer Nebenläufigkeit
- Deptool-Deployments enthalten ein Element optimistischer Nebenläufigkeit.
- Die Planung geht davon aus, dass der aktuelle Cluster-Zustand bekannt ist; falls diese Annahme falsch ist, muss erneut versucht werden.
- Ohne Konkurrenz ist das sehr schnell, etwa bei persönlicher Infrastruktur, die von einer einzelnen Person vom selben Laptop aus deployt wird.
- In Umgebungen, in denen mehrere Personen ständig Deployments anstoßen, kann die Leistung stark leiden, weil nur eine Person erfolgreich ist und alle anderen wiederholen müssen.
- Das Modell ähnelt
git push; es skaliert nicht auf Hunderte Personen oder Tausende Server, ist für persönliche Infrastruktur aber ausreichend.
- Wer sein eigenes Werkzeug baut, kann es exakt auf den eigenen Anwendungsfall optimieren.
Aufbau des Agenten
-
Flatcar Linux und Einschränkungen frischer Hosts
- Der Webserver läuft auf Flatcar Linux.
- Flatcar Linux ist ein image-basiertes Betriebssystem mit sehr kleiner Userspace; coreutils und Bash sind vorhanden, ein Paketmanager und Python jedoch nicht.
- Das ist gut für eine kleinere Angriffsfläche, aber unpraktisch, wenn erst etwas installiert werden muss.
- Wenn ein Werkzeug zunächst etwas installiert haben muss, bevor es funktionieren kann, entsteht sofort ein neues Problem: auch diesen Installationsprozess muss man automatisieren.
-
SSH nur als Transportebene
- Neue Hosts müssen von außen verwaltet werden, daher stehen SSH und passwordless sudo zur Verfügung.
- Befehle direkt per SSH auszuführen ist nicht nur wegen des langsamen Handshakes unattraktiv; auch
argv passiert die SSH-Grenze nicht sicher, und man muss sich mit Word Splitting und Escaping-Problemen von Shell-over-SSH beschäftigen.
- Deptool startet stattdessen ein einzelnes Programm ohne Argumente an einem vorhersagbaren Ort und verwendet dieses Programm als Agenten.
- Der Agent liest Nachrichten von stdin und antwortet über stdout.
- SSH dient damit nur als socket-artiges Transportmittel; benutzergesteuerte Eingaben landen weder in SSH- noch in Shell-Befehlen, wodurch Escaping-Probleme vermieden werden.
-
Verwendung statischer Binärdateien
- Der Agent wird als statische Binärdatei gebaut.
- Damit muss außer dem Kernel nichts vorausgesetzt werden, und es wird auch kein Interpreter benötigt, der erst einige MB Code parsen muss, bevor er etwas Nützliches tun kann.
- Selbst nachdem Ansible seine schlimmsten Schwächen abgemildert hat, überträgt es bei jeder Verbindung immer noch mehrere MB an Python-Modulen; auf Flatcar gibt es zudem gar kein Python.
-
Binärdateien in commit-basierten Pfaden
- Die Agent-Binärdatei wird unter einem Pfad gespeichert, der den gebauten Commit enthält.
- So ist garantiert, dass beide Enden der Verbindung dieselbe Version ausführen und keine Protokollkompatibilitätsprobleme entstehen.
- Das Pfadschema ist
/var/lib/deptool/bin/deptool-<version>-<commit>.
-
Zunächst wird angenommen, dass die Binärdatei bereits vorhanden ist
- SSH-Handshakes sind teuer, daher wird keine Zeit mit Probe- oder idempotenten Installationsschritten verschwendet.
- Die Agent-Binärdatei ist mit etwa 1,6 MB nicht so groß, dass eine Übertragung unzumutbar wäre, aber eben auch nicht kostenlos.
- Änderungen an der Cluster-Konfiguration passieren deutlich häufiger als Updates von Deptool selbst, daher wird normalerweise davon ausgegangen, dass die Binärdatei schon vorhanden ist.
-
Installation der Binärdatei bei Ausführungsfehler
- Falls der Start der Binärdatei fehlschlägt, wird die Installation über eine zweite SSH-Verbindung ausgeführt.
- Der Ausführungsbefehl lautet wie folgt:
uname -sm
&& sudo mkdir -p /var/lib/deptool/{bin,apps,store}
&& sudo dd status=none of=<remote_bin_path>
&& sudo chmod +x <remote_bin_path>
&& sudo sha256sum <remote_bin_path>
- Zuerst wird eine Zeile von stdout gelesen, um die Ausgabe von
uname zu erhalten; darüber werden Betriebssystem und CPU-Architektur bestimmt, um die passende Agent-Binärdatei für diese Plattform zu senden.
- Die Binärdatei wird auf stdin geschrieben, und das entfernte
dd speichert sie auf dem Datenträger.
- Zum Schluss wird eine weitere Zeile von stdout gelesen, um die remote berechnete shasum zu prüfen und die erfolgreiche Übertragung zu verifizieren.
- Dieser Prozess hängt nur von standardisierten coreutils-Programmen ab.
- Ein erneuter Versuch, den Agenten danach zu starten, sollte erfolgreich sein; außerdem räumt der Agent alte Versionen auf, damit der Datenträger nicht vollläuft.
Wirkung und Kosten des Agent-Modells
- Es entsteht eine Möglichkeit, einen Agenten auf dem Remote-Host auszuführen und mit ihm zu kommunizieren.
- Die automatische Installation funktioniert auf Remote-Hosts ohne weitere Anforderungen außer coreutils.
- Weil beide Seiten dieselbe Version ausführen, ist Protokollkompatibilität strukturell garantiert.
- Benutzergesteuerte Eingaben werden ausschließlich über den SSH-basierten Socket transportiert und gelangen nicht in SSH- oder Shell-Befehle, wodurch Escaping-Probleme und Längenlimits vermieden werden.
- Im Normalfall ist nur ein einziger SSH-Handshake nötig, was die Latenz niedrig hält.
- In selteneren Fällen wie bei Deployments auf neue Maschinen oder nach einem Werkzeug-Update sind 2 zusätzliche Verbindungen und eine einmalige Übertragung von 1,6 MB nötig.
- Mit
ControlMaster lässt sich der Großteil des Overheads späterer Verbindungen vermeiden, sodass die Gesamtkosten nur einige Sekunden betragen.
- Damit liegt man zwar nicht mehr unter 1 Sekunde pro Deployment, aber aus Sicht des Autors immer noch besser als mit Ansible.
- Beim typischen Ablauf, eine Konfiguration zu deployen, etwas leicht zu ändern und erneut zu deployen, kann SSH die zugrunde liegende Verbindung offen halten, sodass sich Deployments unmittelbar anfühlen.
Nutzungsergebnisse und Veröffentlichung
- Deptool wird seit dem letzten Monat zur Verwaltung persönlicher Infrastruktur eingesetzt.
- Praktisch sind der sofort sichtbare exakte Plan vor dem Verbindungsaufbau und der automatische Rollback, die größte Veränderung ist aber das Deployment in unter 1 Sekunde.
- Wenn korrektes Deployment mehrere Minuten dauert, entsteht leicht der Wunsch, Dateien direkt auf dem Server zu bearbeiten, um die Feedback-Schleife zu verkürzen; mit Deptool ist lokales Ändern und Deployen jedoch schneller als sich per SSH einzuloggen und einen Editor auf dem Server zu öffnen.
- Der Weg mit der geringsten Reibung wird zum richtigen Weg, und alle angewendeten Änderungen landen in der Git-Historie.
- Selbst wenn etwas kaputtgeht, rollt Deptool zurück, bevor überhaupt bemerkt wird, dass es kaputt ist.
- Deptool wurde gebaut, um exakt ein persönliches Problem zu lösen, und gerade dass es nicht versucht, alle Deployment-Probleme für alle zu lösen, macht es für diesen Anwendungsfall stark.
- Besonders nützlich könnte es auf image-basierten Betriebssystemen sein; veröffentlicht wurde es auf Codeberg und GitHub, dazu gibt es ein ausführliches Handbuch.
1 Kommentare
Lobste.rs-Kommentare
Ich freue mich wirklich darüber, dass offengelegt wurde, dass in dieses Projekt keinerlei LLM-generierter Text eingeflossen ist: not putting LLM-generated text anywhere near this
Das Tool selbst wirkt ebenfalls sehr ausgereift und gut entworfen, aber ich werde wohl vorerst weiter NixOS verwenden
Ich werde das auf jeden Fall ausprobieren. Es wirkt wie eine stärker ausgearbeitete Version eines Systems, das ich selbst gebaut habe, um systemd-basierte Services auszurollen
Das Tutorial sieht gut aus, aber ich frage mich, wie man am besten mit lokalem Zustand umgeht. Zum Beispiel konnte ich in der Dokumentation nicht finden, wo die sqlite-Datenbank einer App gespeichert werden sollte
Außerdem würde mich interessieren, ob es eine Möglichkeit gibt, App-Binärdateien auf den Server zu übertragen und dann von der systemd-Unit verwenden zu lassen. Falls nicht, würde ich gern wissen, wie die Binärverteilung gelöst wird
/var/lib/<yourapp>Wenn die Anwendung als systemd-Unit läuft, kann man
StateDirectory=verwenden, damit systemd das Verzeichnis mit den richtigen Eigentumsrechten für den passenden Benutzer anlegtDie Anwendungen, die ich betreibe, baue ich mit diesem Nix-basierten Skript als kleine EROFS-Images; das Skript enthält auch die Funktion, die Images auf den Server zu pushen. Früher war das ein separater Schritt, inzwischen habe ich Build und Push zu einem Schritt zusammengefasst, und die Images landen in eindeutigen Verzeichnissen, sodass mehrere Versionen parallel existieren können
Das Build-Ergebnis enthält außerdem JSON mit Dateipfaden; diese importiere ich in die Cluster-Konfiguration, rendere daraus systemd-Units und rolle sie dann mit Deptool aus. Ein Tool übernimmt also das Image-Deployment, und Deptool kümmert sich um die Aktivierung
Wenn man Container verwendet, pusht man sie normalerweise in eine Registry, und auf dem Server liegt dann nur noch eine Konfigurationsdatei, die festlegt, was geholt werden soll; diesen Teil kann man daher allein mit Deptool verwalten
Ein anderer Ansatz ist die Verwendung von bootable containers, was ebenfalls ziemlich gut aussieht
Was mir noch fehlt, ist etwas, das auf dem richtigen Host tatsächlich
bootc update --applyausführt. Es gibt zwar einen Auto-Update-Mechanismus, aber der ist nicht koordiniert, und genau das möchte man in einem Cluster nichtIm Moment mache ich das von Hand, aber letztlich muss nur ein einzelner bootc-Befehl ausgeführt werden, daher dürfte es später leicht sein, das zu skripten
Bei jedem neuen Deployment-Tool bin ich erst einmal etwas skeptisch, aber dieses hier wirkt gut entworfen und sauber ausgearbeitet
Dass es direkt den
ssh-Befehl verwendet, scheint ebenfalls die richtige Entscheidung zu sein. Man weiß, dass genau diesesssh, das der Benutzer hat, tatsächlich funktioniert, und es könnte sein, dass jemand eine sehr spezielle Konfiguration oder ein gepatchtes ssh-Binary verwendetTools, die versuchen, ssh über eine externe Bibliothek selbst zu implementieren, stehen für manche Nutzer wahrscheinlich eher im Weg
Ich würde gern mehr darüber erfahren, wie und warum EROFS verwendet wird
Flatcar hat keinen Paketmanager, daher muss man Software und Abhängigkeiten irgendwie selbst auf das System bringen, und ein in sich abgeschlossenes Dateisystem-Image ist eine Möglichkeit dafür
Bei OCI-Images muss ein separates Tool wie Podman oder Docker zuerst das tar irgendwo entpacken und einen Overlay-Mount-Stack aufbauen. Wenn man aber bereits ein Dateisystem-Image hat, kann man es mit
RootImage=direkt aus einer systemd-Unit startenIch baue die Images mit Nix, sodass wirklich nur das absolute Minimum enthalten ist: das Nginx-Binary, LibreSSL, libc und ein paar Shared Libraries, aber nicht einmal Bash
Das ist Teil von Defense in Depth. Selbst wenn es in Nginx eine Remote-Code-Execution-Schwachstelle gäbe, würde der Angreifer in einem Dateisystem-Namespace landen, in dem kaum Material für den nächsten Exploit-Schritt vorhanden ist, und das gesamte Dateisystem ist schreibgeschützt. Nicht nur deshalb, weil es read-only gemountet wurde, sondern weil EROFS überhaupt keine Schreibfunktion hat
Früher habe ich Squashfs verwendet, und das funktionierte gut, aber dieses Dateisystem wurde für das Zeitalter der Live-CDs entworfen. EROFS geht Kompromisse ein, die besser zu heutigen Systemen passen, auch wenn ich ehrlich gesagt in meinem Anwendungsfall keinen messbaren Unterschied erwarten würde
Die Images sind kleiner, aber das liegt daran, dass andere Kompressionseinstellungen verwendet werden. Theoretisch eignet sich EROFS auch besser für content-defined chunking, wenn man Daten zwischen unterschiedlichen Image-Versionen wiederverwenden will, aber ich setze das für die Image-Übertragung derzeit noch nicht praktisch ein
Gerade als ich mit einem Freund über eine einfache Deployment-Strategie sprach, ist dieser Beitrag erschienen, und er liegt ziemlich nah an dem, worauf wir selbst hinausliefen
Mich würde allerdings interessieren, wie in diesem Setup Secret-Management gehandhabt wird
Der Titel war „Prompting the deployment tool I wish I had“, aber
https://codeberg.org/ruuda/deptool/…
In gewisser Weise ist es schon bemerkenswert, dass Gleitkommazahlen dazu gebracht wurden, Rust zu verwenden
Positiv formuliert ist Rust eine „disziplinierte“ Sprache, mit starken Konventionen und einem starken Tooling-Ökosystem. Beides hilft LLMs
Merkwürdigerweise neigen LLMs, zumindest mit etwas Lenkung, dazu, in Rust kürzere Programme zu erzeugen als in manchen anderen Sprachen. Da ich ohnehin vorhabe, jeden Code zu lesen und nachzubearbeiten, ist kürzer für mich besser
Mich würde interessieren, wie dabei Secrets behandelt werden. Gibt es einen bevorzugten Workflow, etwa ob sie in ein EROFS-Image kommen oder über systemd injiziert werden
Dieses Verzeichnis wird für die Lego-Unit mit Lese- und Schreibrechten gemountet und für die Nginx-Unit schreibgeschützt