Mit dav-sync ist es nun möglich, Symlinks zu synchronisieren. Eine Besonderheit dabei ist, dass unter Windows Verknüpfungen von dav-sync als Symlink interpretiert werden. Windows hat zwar auch richtige Symlinks, die sind aber Mist, da normale Benutzer beispielsweise keine anlegen dürfen.
Beim Synchronisieren wird dann für die Verknüpfung oder Symlink eine leere Resource angelegt und die relative Adresse des Targets in einer WebDAV-Property gespeichert. Damit hat man ein automatisches Mapping zwischen Symlinks und Windows-Verknüpfungen. Wer also gerne über Links seine Dateien organisiert, kann dies nun auch plattformübergreifend synchronisieren. Das gibt es sonst nirgends.
Konfigurieren muss man dafür nicht viel. In die sync.xml muss innerhalb des <directory>
-Elements nur folgendes eingefügt werden:
<directory>
...
<symlink-intern>sync</symlink-intern>
</directory>
Synchronisiert werden können dabei nur Links, die ein Target innerhalb des Sync-Directory haben. Links mit externen Targets können aus Sicherheitsgründen nicht synchronisiert werden.
Neben sync
gibt es für das <symlink-intern>
-Element noch zwei Werte, die angegeben werden können. Zum einen follow
, womit angegeben wird, dass Symlinks gefolgt werden soll. Das Ziel wird als normale Datei hochgeladen. Dies ist auch der Default. Die andere Möglichkeit ist ignore
, womit dav-sync dann Symlinks nicht mehr folgt, sondern ignoriert.
Es gibt auch noch das Element <symlink-extern>
für Links mit einem externen Target. Hier sind die Werte follow
und ignore
möglich. Wie erwähnt ist sync
, also das Synchronisieren von externen Links, nicht möglich.
Seit dav-sync 1.3 gibt es das Feature, dass Dateien nicht nur als Ganzes synchronisiert werden können, sondern auch nur Teile einer Datei. Hierfür wird für die Datei eine feste Block-Größe definiert und die Datei wird dann in mehrere Blöcke mit dieser Größe eingeteilt. Lokal wird dann pro Block ein Hash gespeichert, so dass erkannt werden kann, welcher Block geändert wurde und synchronisiert werden muss. Auf dem Server wird statt der Datei eine Collection angelegt, in der die einzelnen Blöcke abgelegt werden.
Das Ganze funktioniert natürlich auch Problemlos mit Verschlüsselung. Jeder Block wird als eigenständige Datei hochgeladen und dabei wie sonst auch mit AES im CBC-Mode verschlüsselt.
Natürlich muss man, um das Feature zu nutzen, mal wieder etwas konfigurieren. Zunächst sollte man sich überlegen, welche Dateien überhaupt zerlegt werden sollen. Mögliche Konfigurationsmöglichkeiten sind zum einen, Dateien mit bestimmten Namen oder Pfaden auszuwählen, zum anderen kann auch eine Mindestdateigröße angegeben werden, ab der Dateien aufgeteilt werden sollen.
Die andere Sache, die man sich überlegen muss, ist, welche Größe die einzelnen Blöcke haben sollen. Diese sollte nicht zu klein sein, da sonst viele tausende kleine Dateien auf dem Server abgelegt werden könnten.
Die Konfiguration erfolgt dann in der Datei sync.xml. Hier muss innerhalb des Sync-Directory folgendes eingefügt werden:
<directory>
...
<splitconfig>
<!-- split all files with .vmdk file extension that are bigger than 100mb -->
<split>
<blocksize>10m</blocksize>
<filter>
<include>\.vmdk$</include>
</filter>
<minsize>100m</minsize>
</split>
</splitconfig>
</directory>
Pflichtangabe ist das Element <blocksize>
. Damit wird die Blockgröße in Bytes, alternativ auch mit einem Suffix wie k, m oder g, angegeben. Dazu muss entweder <minsize>
oder ein <filter>
definiert sein. Beides zusammen geht natürlich auch.
Mit <filter>
können Regex-Filter, die auf den Dateipfad angewendet werden, konfiguriert werden. Möglich sind zum einen <include>
-Filter, die zunächst definieren, welche Dateien ausgewählt werden sollen. Dies kann dann noch mit <exclude>
eingeschränkt werden. Die Doku enthält dazu mehr Details.
Mit <minsize>
gibt man die Größe an, die eine Datei mindestens haben muss, damit sie aufgeteilt wird. Gibt man nur dieses Element an, ohne <filter>
, kann man also pauschal alle Dateien ab einer bestimmten Größe splitten.
Es können auch mehrere split-Regeln definiert werden. Dazu muss nur innerhalb des Elements <splitconfig>
ein weiteres <split>
-Element eingefügt werden.
Mehr als die Konfiguration muss man dann auch nicht tun. An der Benutzung von dav-sync ändert sich nichts. Wenn alles korrekt konfiguriert ist, werden dann die entsprechenden Dateien aufgeteilt und nur geänderte Blöcke der Datei werden übertragen. Der Benutzer kriegt davon erstmal nichts mit, außer dass es vielleicht schneller geht.
Eine Einschränkung gibt es allerdings. Datei-Versionierung funktioniert nicht mit gesplitteten Dateien. Genauso funktioniert es nicht, wenn <backup-on-pull>true</backup-on-pull>
für das Sync-Directory konfiguriert ist, dass bei jeder Dateiänderung ein Backup der Datei in das Trash-Verzeichnis verschoben wird. Der Grund ist, dass nicht mehr kostengünstig über ein move die Datei gesichert werden kann, weil keine komplette Datei übertragen wird.
Erwähnenswert wäre auch noch, dass Datei-Splitting ohne Konfiguration der sync.xml möglich wäre, denn es kann im Prinzip pro Datei einzelnd festgelegt werden, ob diese gesplittet werden soll. Einfache dav-sync-Befehle, um das festzulegen, haben es jedoch nicht in das Release geschafft und ohne Befehle wäre das zu Hacky für diesen Artikel.
Ich habe in dav-sync von Anfang an die Datensicherheit an erste Stelle gestellt. Geprägt von Horrorgeschichten über Synchronisations-Programme, die massenweise Daten niedergemetzelt haben, wollte ich mir und allen dav-sync Usern dies ersparen. Daher gab es schon von Anfang an als zusätzliche Sicherung das Trash-Verzeichnis, in das Dateien verschoben wurden, statt sie zu löschen.
Neu ist jetzt das Versioning-Feature, womit auf dem Server mehrere Versionen von Dateien gespeichert werden können. Dies ist in zwei Varianten implementiert. Einmal über einfache Kopien von den Dateien, die in einer versteckten Collection abgelegt werden. Die andere Variante nutzt die WebDAV-Erweiterung DeltaV, wofür es jedoch praktisch keine Server-Implementierungen gibt. Noch nicht ;-)
Im Folgenden möchte ich die Konfiguration und die Benutzung der dav-sync Versionierung erläutern.
Zunächst benötigt man natürlich erst einmal eine Konfiguration für ein Verzeichnis, welches synchronisiert werden soll. In diesem Artikel habe ich die Einrichtung und grundlengende Benutzung von dav-sync erklärt. Für die Versionierung muss nur noch die Konfiguration (sync.xml) etwas angepasst werden. Hierfür muss nur innerhalb des <directory>
-Elements folgendes ergänzt werden:
<versioning type="simple" always="true" />
Das type="simple"
steht für die Versionierung über einfache Kopien der Dateien. Alternativ könnte hier statt simple
auch deltav
stehen. Hierfür benötigt man natürlich einen DeltaV-kompatiblen Server. Apache, Nextcloud oder praktisch alle anderen WebDAV-Server unterstützten dies jedoch nicht.
Das Attribut always="true"
gibt an, dass bei jedem Hochladen einer Datei eine neue Version angelegt werden soll. Hier könnte natürlich auch false
angegeben werden, dann wird nur eine neue Version gespeichert, wenn dies manuell angefordert wird. Hierfür gibt es für die dav-sync Kommandos push und archive die Option -S
. Wird diese angegeben, wird für jede hochgeladene Datei die vorherige Version gespeichert.
Damit ist die Konfiguration auch schon abgeschlossen. Alte Versionen von Dateien werden standardmäßig in der Collection .dav-version-history (unterhalb des Sync-Directory) abgelegt. Wer will könnte noch den Speicherort der Versions-History mit dem <history>
-Element anpassen.
<versioning type="simple" always="true">
<history>/.backup/</history>
</versioning>
Jetzt werden immer alte Versionen von Dateien gespeichert. Wer hingegen always="false"
benutzt, kann beim Uploaden von Dateien folgendermaßen die Version speichern:
$ dav push -S mydir
Um jetzt alte Versionen von Dateien wiederherzustellen, benötigt man zwei dav-sync Befehle: list-versions und restore. Beide Befehle arbeiten mit lokalen Dateipfaden, man kann daher einen absoluten oder relativen Pfad zu der Datei angeben und dav-sync bestimmt dann automatisch das passende Sync-Directory dazu (wenn es eindeutig ist, ansonsten muss man es mit der Option -s
angeben). Als Beispiel gehen wir davon aus, dass wir uns in der Shell im Verzeichnis befinden, in dem die Datei liegt.
$ dav-sync list-versions test.txt
name: 1576420562-69ba29c77659c2db
lastmodified: Sun, 15 Dec 2019 10:39:30 GMT
url: https://example.com/webdav/.history/157/1576420562-69ba29c77659c2db
name: 1576420572-b6a1862b0b1c04e6
lastmodified: Sun, 15 Dec 2019 11:12:28 GMT
url: https://example.com/webdav/.history/157/1576420572-b6a1862b0b1c04e6
name: 1576420613-8b1260a7a6943580
lastmodified: Sun, 15 Dec 2019 15:33:06 GMT
url: https://example.com/webdav/.history/157/1576420613-8b1260a7a6943580
list-versions zeigt alle verfügbaren vorherigen Versionen einer Datei an. Was wir aus der Ausgabe benötigen ist das Feld name. Den Namen können wir bei dem Befehl restore benutzen, um diese Version wiederherzustellen.
$ dav-sync restore -V 576420572-b6a1862b0b1c04e6 test.txt
get: /test.txt
Result: 1 file pulled, 0 errors
Dies downloaded die angegebene Version und ersetzt damit die lokale Datei.
Eine Einschränkung ist noch, dass es keine einfache Möglichkeit gibt, gelöschte Dateien wiederherzustellen. Wenn man versehentlich eine Datei löscht, kann man unmittelbar danach zwar mit dav-sync restore -s <syncdir>
alle gelöschten Dateien wiederherstellen. Dies funktioniert jedoch nicht mehr, sobald man nach dem Löschen den Befehl push ausführt und somit auf dem Server die Datei gelöscht wird. Dann ist die Datei zwar noch in der History vorhanden, es gibt jedoch keinen Befehl, der die Datei wiederherstellen kann. Da bleibt einem nur übrig, die gesamte History zu durchsuchen.
Dieser Artikel ist ein Step-by-step Howto für die Einrichtung von dav-sync mit aktivierter Verschlüsselung.
1. Repository konfigurieren
Zuerst erstellen wir ein Repository mit Hilfe des add-repository
Befehls von dav. Wichtig ist, dass wir dabei auch Benutzername und Passwort angeben, da dav-sync Authentifizierungsinformationen benötigt und diese nicht zur Laufzeit vom Benutzer abfragt.
$ dav add-repository
Each repository must have an unique name.
name: myfirstrepo
Specify the repository base url.
url: https://mynas.local/webdav
User for HTTP authentication.
user (optional): mywebuser
password (optional):
2. Key erstellen und konfigurieren
Als nächstes benötigt man einen AES-Key. Diesen erstellen wir aus zufälligen Daten mit Hilfe von dd:
mkdir -p ~/.dav/keys
dd if=/dev/random of=~.dav/keys/mykey bs=32 count=1
Dann muss in der Datei $HOME/.dav/config.xml
nur noch ein Eintrag für den Key hinzugefügt werden.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
...
<key>
<name>mykey</name>
<type>aes256</type>
<file>keys/mykey</file>
</key>
</configuration>
3. Verschlüsselung für das Repository aktivieren
Wärend man mit dem Tool dav die Verschlüsselung per Kommandozeilenoption an- und abschalten kann, benutzt dav-sync immer die Default-Einstellungen des Repositories. Daher muss für das Repository die Verschlüsselung standardmäßig aktiviert sein und ein Default-Key muss angegeben werden. Hierfür fügt man innerhalb des <repository>
-Elements das <full-encryption>
und <default-key>
-Element hinzu:
<repository>
...
<full-encryption>true</full-encryption>
<default-key>mykey</default-key>
</repository>
3. Sync-Directory erstellen
Letztendlich benötigt man noch die eigentliche Konfiguriation für dav-sync. Mit dem Befehl add-directory
von dav-sync erstellen wir die Konfiguration für ein Sync-Directory. Dabei gibt man dann das Repository mit aktivierter Verschlüsselung an:
$ dav-sync add-directory
Each sync directory must have an unique name.
name: mysyncdir
Enter local directory path.
path: $HOME/important_files
Specify webdav repository.
0) myfirstrepo
1) anotherrepo
repository: 0
Enter collection relative to the repository base url.
collection (default: /): /important_files
Fertig. Für den Benutzer ändert sich an der Bedienung von dav-sync dann nichts. Man kann ganz wie gewohnt mit pull/push seine Dateien synchronisieren, nur dass sie dann verschlüsselt auf dem Server liegen.
Teil des dav Pakets ist das separate Tool dav-sync, das lokale Verzeichnisse mit WebDAV-Collections synchronisieren kann.
Features
- Verwendet die selbe Repository-Konfiguration von dav, womit Dinge wie Verschlüsselung oder Proxies zur Verfügung stehen
- Separate Befehle um die Änderungen vom Servers zu downloaden und um die lokalen Änderungen auf den Server zu übertragen
- Konflikterkennung
- Trash-Verzeichnis, in dem Dateien, die gelöscht oder überschrieben werden sollen, abgelegt werden können
- Regex-Filter, um bestimmte Dateien einzubeziehen und/oder auszuschließen
Funktionsweise
Jedes Sync-Directory hat eine Datenbank (in Wahrheit nur eine billige XML-Datei), in der Zustandsinformationen jeder Datei gespeichert sind. Im Detail sind das der Etag, die Dateigröße und das Datum der letzten Änderung. Diese Informationen werden genutzt um Änderungen zu erkennen. Um Änderungen auf dem Server zu erkennen, wird der Etag jeder Datei verglichen und um lokale Änderungen zu erkennen wird das Änderungsdatum und die Dateigröße mit den Werten in der Datenbank verglichen.
Konfiguration
Zunächst einmal muss ein Repository für den Server konfiguriert werden. Am einfachsten geht dies mit dem Befehl dav add-repository
. Siehe meinen Artikel zu dem Thema.
Als nächstes muss noch das lokale Verzeichnis in der Datei $HOME/.dav/sync.xml
konfiguriert werden. Eine einfache Basiskonfiguration kann mit dem Befehl dav-sync add-directory
angelegt werden.
Dies fragt zuerst nach einem frei wählbaren Identifier für das Verzeichnis, der dann auch mit den anderen dav-sync Befehlen genutzt wird. Danach muss der lokale Pfad angegeben werden, wobei man im Pfad auch Umgebungsvariablen wie $HOME verwenden kann. Danach folgt noch das Repository und die Collection des Repositories, in welche die Dateien dann synchronisiert werden sollen. Die volle URL ist der angegebene Collection-Pfad angehängt an die Basis-URL des Repositories.
$ dav-sync add-directory
Each sync directory must have an unique name.
name: mysyncdir
Enter local directory path.
path: $HOME/important_files
Specify webdav repository.
0) myfirstrepo
1) anotherrepo
repository: 0
Enter collection relative to the repository base url.
collection (default: /): /important_files
Danach kann man seine Daten mit den Befehlen pull
und push
synchronisieren. Es werden von dav-sync alle Einstellungen des Repositories verwendet, also Authentication-Informationen, TLS-Einstellungen und AES-Verschlüsslung. Zu beachten ist auch, dass dav-sync keinen Authentication-Prompt anzeigt, daher müssen Authentication-Daten im Repository konfiguriert sein.
Anwendung
Für die Synchronisation gibt es primär zwei Befehle: pull, um Dateien, die auf dem Server geändert wurden, zu downloaden und push, um lokale Änderungen auf den Server zu uploaden. Man gibt dabei nur den Identifier des Verzeichnisses an, z.B. um Änderungen zu downloaden:
dav-sync pull mysyncdir
Änderungen uploaden geht mit:
dav-sync push mysyncdir
Wer komplett das Verzeichnis mit dem Server synchronisieren will, damit sie den gleichen Zustand haben, sollte zunächst pull und danach push aufrufen:
$ dav-sync pull mysyncdir
...
$ dav-sync push mysyncdir
...
Im besten Fall werden dabei einfach nur Dateien gedownloadet bzw geuploadet. Wenn jedoch Dateien lokal und auf dem Server geändert wurden, führt dies zu einem Konflikt. Der push-Befehl ignoriert solche Dateien einfach. Beim pull-Befehl wird die entsprechende Datei umbenannt und die Version des Servers wird unter dem originalen Namen gespeichert. Der Anwender muss dann selber die Dateien vergleichen und entscheiden welche er behalten will. Die umbenannten Dateien der Form orig.$number.$name werden im übrigen von push ignoriert, da sie als Konflikt markiert sind. Wer sie trotzdem uploaden will, kann sie einfach umbenennen oder mit dav-sync resolve-conflicts <syncdir>
die Konfliktmarkierung entfernen, wonach sie für dav-sync ganz normale Dateien sind. Mit dav-sync delete-conflicts <syncdir>
können auch alle diese Dateien entfernt werden.
Gelöschte und überschriebene Dateien wiederherstellen
Wie anfangs erwähnt unterstützt dav-sync ein Trash-Verzeichnis, in das es alle Dateien verschiebt, anstatt sie zu löschen. Wenn mit dav-sync add-directory
das Sync-Directory angelegt wurde, ist das Trash-Verzeichnis auch standardmäßig aktiviert und ist das .trash Unterverzeichnis des Sync-Directory.
Wann immer pull also eine Datei löschen will, wird diese dann in das Trash-Verzeichnis verschoben. Das schützt schon mal vor unbeabsichtigten Löschen. Es gibt zusätzlich noch die Möglichkeit, dass auch Dateien, bevor sie durch den pull-Befehl überschrieben werden, in das Trash-Verzeichnis verschoben werden. Hierfür muss in der sync.xml innerhalb des entsprechenden <directory>
-Elements folgendes eingefügt werden:
<directory>
...
<backup-on-pull>true</backup-on-pull>
</directory>
Diese Datensicherheit hat natürlich den Preis, dass viele Kopien einer Datei irgendwann rumliegen. Mit dav-sync trash-info <directory>
erhält man einen Überblick darüber, wie viele Dateien im Trash sind, und wie viel Platz sie verbrauchen. Wer das Trash-Verzeichnis leeren will, kann hierfür dav-sync empty-trash <directory>
benutzen.