Vaultwarden Backup mit Rclone

Vaultwarden ist eine alternative Implementation der Bitwarden Server API entwickelt in Rust, kompatibel mit allen Bitwarden clients. Vaultwarden eignet sich daher perfekt für self-hosted deployments, oder überall dort wo der offizielle Bitwarden Service nicht ideal geeignet ist. Dazu gibt es einmal das Vaultwarden Docker Image und den dazu gehörenden SourceCode auf Github.

Doch wie kann ich nun meine Vaultwarden Docker Instanz sichern? Dazu kann ich das Docker Image von https://github.com/ttionya/vaultwarden-backup empfehlen, das folgende Möglichkeiten bringt:

Backup der folgenden Dateien und Verzeichnisse:

  • db.sqlite3
  • config.json
  • rsa_key* (mehrere Dateien)
  • attachments (Verzeichnis)
  • sends (Verzeichnis)

Weiter ist es möglich über den Backup-Status notifiziert zu werden mittels:

  • Ping (sendet nur bei erfolgreichem Backup)
  • Mail (SMTP basiert, sendet bei Backup Erfolg und Fehler)

Nun stellt sich die Frage wohin sichern mit valtwarden-backup? Dazu habe ich an einem anderen Gerät in meinem Netzwerk eine externe USB Disk, auf welche ich die Backups mittels Rclone senden kann. Rclone lässt sich in vaultwarden-backup wie folgt einrichten:

docker run --rm -it \
    --mount type=volume,source=vaultwarden-rclone-data,target=/config/ \
    ttionya/vaultwarden-backup:latest \
    rclone config

Mit diesem Aufruf lässt sich innerhalb von vaultwarden-backup Rclone konfigurieren:

2022/05/24 05:50:00 NOTICE: Config file "/config/rclone/rclone.conf" not found - using defaults
No remotes found, make a new one?
n) New remote
s) Set configuration password
q) Quit config
n/s/q> 

Wir geben "n" an für eine neue Konfiguration:

n/s/q>n

Anschliessend eine passende Bezeichnung für die Rclone Konfiguriation:

name> rclone-backup

Nun werden alle Rclone Backup Optionen aufgelistet:

Option Storage.
Type of storage to configure.
Choose a number from below, or type in your own value.
 1 / 1Fichier
   \ (fichier)
 2 / Akamai NetStorage
   \ (netstorage)
 3 / Alias for an existing remote
   \ (alias)
 4 / Amazon Drive
   \ (amazon cloud drive)
 5 / Amazon S3 Compliant Storage Providers including AWS, Alibaba, Ceph, China Mobile, Digital Ocean, Dreamhost, IBM COS, Lyve Cloud, Minio, Netease, RackCorp, Scaleway, SeaweedFS, StackPath, Storj, Tencent COS and Wasabi
   \ (s3)
 6 / Backblaze B2
   \ (b2)
 7 / Better checksums for other remotes
   \ (hasher)
 8 / Box
   \ (box)
 9 / Cache a remote
   \ (cache)
10 / Citrix Sharefile
   \ (sharefile)
11 / Compress a remote
   \ (compress)
12 / Dropbox
   \ (dropbox)
13 / Encrypt/Decrypt a remote
   \ (crypt)
14 / Enterprise File Fabric
   \ (filefabric)
15 / FTP Connection
   \ (ftp)
16 / Google Cloud Storage (this is not Google Drive)
   \ (google cloud storage)
17 / Google Drive
   \ (drive)
18 / Google Photos
   \ (google photos)
19 / Hadoop distributed file system
   \ (hdfs)
20 / Hubic
   \ (hubic)
21 / In memory object storage system.
   \ (memory)
22 / Jottacloud
   \ (jottacloud)
23 / Koofr, Digi Storage and other Koofr-compatible storage providers
   \ (koofr)
24 / Local Disk
   \ (local)
25 / Mail.ru Cloud
   \ (mailru)
26 / Mega
   \ (mega)
27 / Microsoft Azure Blob Storage
   \ (azureblob)
28 / Microsoft OneDrive
   \ (onedrive)
29 / OpenDrive
   \ (opendrive)
30 / OpenStack Swift (Rackspace Cloud Files, Memset Memstore, OVH)
   \ (swift)
31 / Pcloud
   \ (pcloud)
32 / Put.io
   \ (putio)
33 / QingCloud Object Storage
   \ (qingstor)
34 / SSH/SFTP Connection
   \ (sftp)
35 / Sia Decentralized Cloud
   \ (sia)
36 / Storj Decentralized Cloud Storage
   \ (storj)
37 / Sugarsync
   \ (sugarsync)
38 / Transparently chunk/split large files
   \ (chunker)
39 / Union merges the contents of several upstream fs
   \ (union)
40 / Uptobox
   \ (uptobox)
41 / Webdav
   \ (webdav)
42 / Yandex Disk
   \ (yandex)
43 / Zoho
   \ (zoho)
44 / http Connection
   \ (http)
45 / premiumize.me
   \ (premiumizeme)
46 / seafile
   \ (seafile)

Ich verwende Option 34 (34 / SSH/SFTP Connection):

  Storage> 34

Jetzt muss ich den Host, auf welchem ich die externe USB Disk bereitgestellt habe angeben:

  Option host.
  SSH host to connect to.
  E.g. "example.com".
  Enter a string value. Press Enter for the default ("").
host> backup-nas.local

Der Benutzername mit welchem sich Rclone am Zielsystem authentifizieren kann:

Option user.
SSH username.
Enter a string value. Press Enter for the default (root).
user> backup-service-account

Als nächstes kann man den SSH Port angeben (falls man nicht 22 verwendet), weiter möchte ich ein Kennwort angeben (noch besser ist die Kennwortlose Authentifizierung nur mit SSH-Keys):

Option port.
SSH port number.
Enter a signed integer. Press Enter for the default (22).
port> 
Option pass.
SSH password, leave blank to use ssh-agent.
Choose an alternative below. Press Enter for the default (n).
y) Yes, type in my own password
g) Generate random password
n) No, leave this optional password blank (default)
y/g/n> y

Es folgt ein Marathon von weiteren Optionen, welche ich zur Zeit nicht verwenden will und deshalb mit den default Werten (Enter) bestätige:

Option key_pem.
Raw PEM-encoded private key.
If specified, will override key_file parameter.
Enter a value. Press Enter to leave empty.
key_pem> 
Option key_file.
Path to PEM-encoded private key file.
Leave blank or set key-use-agent to use ssh-agent.
Leading `~` will be expanded in the file name as will environment variables such as `${RCLONE_CONFIG_DIR}`.
Enter a value. Press Enter to leave empty.
key_file> 
Option key_file_pass.
The passphrase to decrypt the PEM-encoded private key file.
Only PEM encrypted key files (old OpenSSH format) are supported. Encrypted keys
in the new OpenSSH format can't be used.
Choose an alternative below. Press Enter for the default (n).
y) Yes, type in my own password
g) Generate random password
n) No, leave this optional password blank (default)
y/g/n> 
Option pubkey_file.
Optional path to public key file.
Set this if you have a signed certificate you want to use for authentication.
Leading `~` will be expanded in the file name as will environment variables such as `${RCLONE_CONFIG_DIR}`.
Enter a value. Press Enter to leave empty.
pubkey_file> 
Option key_use_agent.
When set forces the usage of the ssh-agent.
When key-file is also set, the ".pub" file of the specified key-file is read and only the associated key is
requested from the ssh-agent. This allows to avoid `Too many authentication failures for *username*` errors
when the ssh-agent contains many keys.
Enter a boolean value (true or false). Press Enter for the default (false).
key_use_agent> 
Option use_insecure_cipher.
Enable the use of insecure ciphers and key exchange methods. 
This enables the use of the following insecure ciphers and key exchange methods:
- aes128-cbc
- aes192-cbc
- aes256-cbc
- 3des-cbc
- diffie-hellman-group-exchange-sha256
- diffie-hellman-group-exchange-sha1
Those algorithms are insecure and may allow plaintext data to be recovered by an attacker.
Choose a number from below, or type in your own boolean value (true or false).
Press Enter for the default (false).
 1 / Use default Cipher list.
   \ (false)
 2 / Enables the use of the aes128-cbc cipher and diffie-hellman-group-exchange-sha256, diffie-hellman-group-exchange-sha1 key exchange.
   \ (true)
use_insecure_cipher> 
Option disable_hashcheck.
Disable the execution of SSH commands to determine if remote file hashing is available.
Leave blank or set to false to enable hashing (recommended), set to true to disable hashing.
Enter a boolean value (true or false). Press Enter for the default (false).
disable_hashcheck> 
Edit advanced config?
y) Yes
n) No (default)
y/n> 
--------------------
[rclone-backup]
type = sftp
host = backup-nas.local
user = backup-service-account
pass = *** ENCRYPTED ***
--------------------
y) Yes this is OK (default)
e) Edit this remote
d) Delete this remote
y/e/d> y
Current remotes:

Name                 Type
====                 ====
rclone-backup        sftp

e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> q

Mit dem folgenden Befehl sollten wir nun das Docker Volume dieses Containers sehen:

user@myhost:~ $ docker volume ls
DRIVER    VOLUME NAME
local     vaultwarden-rclone-data

Auch können wir nun prüfen, ob darin die Rclone Konfiguration korrekt gespeichert ist, indem wir diese aufrufen, dieser Befehl sollte unsere vorherige Konfiguration ausgeben:

user@myhost:~ $ docker run --rm -it   --mount type=volume,source=vaultwarden-rclone-data,target=/config/   ttionya/vaultwarden-backup:latest   rclone config show

Ich habe zudem eine Mail Notifizierung via Gmail konfiguriert, damit sieht das docker-compose File letztendlich wie folgt aus:

  backup:
    image: ttionya/vaultwarden-backup:latest
    restart: always
    volumes:
      - /var/docker/vaultwarden:/bitwarden/data/:ro
      - /var/docker/vaultwarden-rclone-data:/config/:ro
    environment:
      RCLONE_REMOTE_NAME: 'remote'
      RCLONE_REMOTE_DIR: '/Backup/'
      CRON: '0 18 * * *'
      ZIP_ENABLE: 'TRUE'
      ZIP_PASSWORD: 'yourpasswordhere'
      ZIP_TYPE: 'zip'
      #BACKUP_FILE_DATE_SUFFIX: ''
      BACKUP_KEEP_DAYS: 7
      #PING_URL: ''
      MAIL_SMTP_ENABLE: 'TRUE'
      MAIL_SMTP_VARIABLES: '-S smtp-use-starttls -S ssl-verify=true -S smtp-auth=login -S smtp=smtp://smtp.gmail.com:587 -S from=yourmailhere -S smtp-auth-user=yourmailhere -S smtp-auth-password=yourpasswordhere -S ssl-verify=true'
      MAIL_TO: 'yourmailhere'
      MAIL_WHEN_SUCCESS: 'TRUE'
      MAIL_WHEN_FAILURE: 'TRUE'
      TIMEZONE: 'Europe/Zurich'

Der Mailversand lässt sich mit diesem Befehl testen, natürlich müssen zuerst noch die Variabeln von vorhin eingetragen werden:

user@myhost:~ $ docker run --rm -it -e MAIL_SMTP_VARIABLES='-S smtp-use-starttls  ....' -e MAIL_TO='yourmailhere' ttionya/vaultwarden-backup:latest mail

Ob der Mailversand funktioniert zeigt sich damit, ob dieser Befehlt zuletzt 

mail send was successfully

ausgibt und ob nun eine EMail im Postfach landet mit dem Inhalt:

Your SMTP looks configured correctly.