Ich nutze seit einiger Zeit den Passwortmanager Bitwarden bzw. Vaultwarden (neuer Name des bitwarden_rs-Projektes) und bin sehr zufrieden.

Einziges schlechtes Gefühl bei der Sache: Wenn mir der Server abraucht oder mal bei einem Docker-Experiment etwas schief läuft, dann habe ich mir vielleicht von meinen Passwörtern ab und an ein manuelles Backup gezogen, auf welches ich zurückgreifen kann; alle anderen Nutzer, denen ich Bitwarden/Vaultwarden auf's Auge gedrückt habe, stehen aber dumm da (weil kein normaler Mensch in meinem Umkreis sich um Backups schert. Macht ja heutztage sowieso "die Cloud").

Nun habe ich mir ein Skript zusammengezimmert, welches täglich die sqlite3-Datenbank von Vaultwarden aus dem Docker-Container rauskopiert.
Sollte irgendwas mal schief gehen, weiß ich zwar noch nicht, wie ich die Datenbank in eine Neuinstallation rein bekomme, aber immerhin habe ich mal eine aktuelle Kopie der Datenbank ;-)

Disclaimer: Dieser Artikel ist nur hilfreich, wenn man Vaultwarden mit einer sqlite3-Datenbank betreibt (bis vor einiger Zeit bei Vaultwarden aka. bitwarden_rs die einzige Möglichkeit).

launchd

Mein Skript wir täglich per launchd ausgeführt.

Wichtig ist, dass es im selben Benutzeraccount läuft, in welchem man auch problemlos das Docker-Kommando verwenden kann, sonst kann sich das Backup-Skript nachher nicht mit dem Docker-Daemon verbinden.

Also entweder launchd-plist-Datei unter ~/Library/LaunchAgents ablegen oder wie in meinem Fall, wo die Datei unter /Library/LaunchDaemons liegt, den betreffenden UserName mitgeben, als welcher das Skript laufen soll.

Weil ich selbst wieder darüber gestolpert bin: Dieser Benutzer muss Schreibrechte für die unter StandardErrorPath und StandardOutPath angegebene log-Datei haben!

de.apfelz.vaultwardenBackup.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>de.apfelz.vaultwardenBackup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/server/scripts/launchd/vaultwarden-db-backup.sh</string>
    </array>
    <key>StandardErrorPath</key>
    <string>/Library/Logs/apfelz/vaultwarden-db-backup.log</string>
    <key>StandardOutPath</key>
    <string>/Library/Logs/apfelz/vaultwarden-db-backup.log</string>
    <key>StartCalendarInterval</key>
        <dict>
        <key>Minute</key>
        <integer>40</integer>
        <key>Hour</key>
        <integer>23</integer>
        </dict>
   <key>UserName</key>
   <string>apfelz</string>
   <key>GroupName</key>
   <string>wheel</string>
</dict>
</plist>

Skript

Nun das Skript, welches die sqlite3-Datenbank aus dem Docker-Container holt und auf meiner Backup-Platte abspeichert.

In der ausgeführten Umgebung ist sowohl /usr/local/bin/ nicht im PATH enthalten, weswegen ein im Hintergrund notwendiger VBoxManage-Befehl nicht ausgeführt werden kann, auch die Docker-Environment-Variablen sind der Shell nicht mehr bekannt.
Deshalb füge ich hier erst wieder /usr/local/bin/ dem PATH hinzu und führe darauf das Kommando aus, welches die Docker-Environment-Variablen in die Shell-Umgebung lädt.

Danach wird mit docker cp vaultwarden:/data /tmp/ das gesamte data-Verzeichnis aus dem Docker-Container in das lokale /tmp-Verzeichnis des Servers kopiert, ein .tbz-Archiv daraus gemacht und auf meiner Backup-Platte abgelegt (von wo es noch versioniert archiviert und zu meinen Eltern nach Hause gesendet wird. Sicher ist sicher).

Optional kann man die vaultwarden-Instanz noch vor dem Backup pausieren (damit man sie nicht just in dem Moment kopiert, in dem ein Zugriff stattfindet...wobei bei nur gelegentlichem Sync und 3-4 Familien-Nutzern nachts eher keine Zugriffe zu erwarten sind) und danach weiterlaufen lassen.

vaultwarden-db-backup.sh
# Erstellt ein Backup der Vaultwarden sqlite3-Datebank in Docker

BACKUPPATH="/Volumes/TimeCapsule/sql"

# Environment-Variablen setzen
PATH=$PATH:/usr/local/bin/
eval "$(docker-machine env default)"

# Optional pausieren
docker pause vaultwarden

# Aus dem Container hinaus in das "reale Dateisystem" kopieren
docker cp vaultwarden:/data /tmp/

# Weiterlaufen lassen, falls pausiert
docker unpause vaultwarden

# Backup verpacken
tar --exclude='icon_cache' -cjf $BACKUPPATH/baultwarden.tbz -C /tmp/data/ . 2>/dev/null
rm -r /tmp/data

Was ich im Notfall mit so einem Backup anstelle, ist in diesem Artikel zu lesen.