/vaultwarden-backup-s3

Fork of https://github.com/Bruceforce/vaultwarden-backup that implements backup to s3 storage bucket.

Primary LanguageShell

Vaultwarden Backup

A simple cron powered backup image for vaultwarden.

Why vaultwarden-backup?

You might ask yourself "Why should I use a container for backing up my vaultwarden files if I can just include them in my regular backup?". One caveat of using regular backup software for database is, that you shoud always stop your database server before you make a backup or you will risk data loss. To prevent this a proper backup command for your database should be used.

Of course you could just create a cron job on your host with something like sqlite3 "$VW_DATABASE_URL" ".backup '$BACKUP_FILE_DB'" and back up the additional files and folders (like the attachments folder), using your preferred backup solution.

However on some systems you are not able to add cronjobs by yourself, for example common NAS venderos don't allow this. That's why this image exists. Additionally it also includes the most important files and puts them in a tar.gz archive from where on your regular backup software could handle this files.

Which files are included in the backup?

By default all files that are recommended to backup by the official Vaultwarden wiki https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault are backed up per default.

Usage

Since version v0.0.7 you can always use the latest tag, since the image is build with multi-arch support. Of course you can always use the version tags vx.y.z to stick to a specific version. Note however that there will be no security updates for the alpine base image if you stick to a version.

Make sure that your vaultwarden container is named vaultwarden otherwise you have to replace the container name in the --volumes-from section of the docker run call.

Automatic Backups

A cron daemon is running inside the container and the container keeps running in background.

Start backup container with default settings (automatic backup at 5 am)

docker run -d --restart=always --name vaultwarden-backup --volumes-from=vaultwarden bruceforce/vaultwarden-backup

Example for hourly backups

docker run -d --restart=always --name vaultwarden-backup --volumes-from=vaultwarden -e CRON_TIME="0 * * * *" bruceforce/vaultwarden-backup

Example for backups that delete after 30 days

docker run -d --restart=always --name vaultwarden --volumes-from=vaultwarden -e TIMESTAMP=true -e DELETE_AFTER=30 bruceforce/vaultwarden-backup

Manual Backups

You can use the crontab of your host to schedule the backup and the container will only be running during the backup process.

docker run --rm --volumes-from=vaultwarden bruceforce/vaultwarden-backup manual

If you want the backed up file to be stored outside the container you have to mount a directory by adding -v <PATH_ON_YOUR_HOST>:<PATH_INSIDE_CONTAINER>. The complete command could look like this

docker run --rm --volumes-from=vaultwarden -e UID=0 -e BACKUP_DIR=/myBackup -e TIMESTAMP=true -v $(pwd)/myBackup:/myBackup bruceforce/vaultwarden-backup manual

Keep in mind that the commands will be executed inside the container. So $BACKUP_DIR can be any place inside the container. Easiest would be to set it to /data/backup which will create the backup next to the original database file.

Restore

There is no automated restore process to prevent accidential data loss. So if you need to restore a backup you need to do this manually by following the steps below (assuming your backups are located at ./backup/ and your vaultwarden data ist located at /var/lib/docker/volumes/vaultwarden/_data/)

# Delete any existing sqlite3 files
rm /var/lib/docker/volumes/vaultwarden/_data/db.sqlite3*

# Copy the database to the vaultwarden folder
cp ./backup/db.sqlite3 /var/lib/docker/volumes/vaultwarden/_data/db.sqlite3

# Extract the additional folder from the archive
tar -xzvf ./backup/data.tar.gz -C /var/lib/docker/volumes/vaultwarden/_data/

Environment variables

ENV Description Default
BACKUP_ADD_DATABASE 1 Set to true to include the database itself in the backup true
BACKUP_ADD_ATTACHMENTS 1 Set to true to include the attachments folder in the backup true
BACKUP_ADD_CONFIG_JSON 1 Set to true to include config.json in the backup true
BACKUP_ADD_ICON_CACHE 1 Set to true to include the icon cache folder in the backup false
BACKUP_ADD_RSA_KEY 1 Set to true to include the RSA keys in the backup true
BACKUP_ADD_SENDS 1 Set to true to include the sends folder in the backup false
BACKUP_DIR Sets the path of the backup folder inside the container /backup
BACKUP_DIR_PERMISSIONS Sets the permissions of the backup folder (CAUTION 2). Set to -1 to disable. 700
COPY_BACKUP_TO_S3 Set to true to copy backed-up files to s3 bucket false
AWS_BUCKET_NAME Sets the name of the destination s3 bucket unset
AWS_BUCKET_PATH Sets the path of file destination inside s3 bucket unset
AWS_ACCESS_KEY Sets the access key to s3 bucket. unset
AWS_SECRET_KEY Sets the secret key to s3 bucket. unset
CRONFILE Path to the cron file inside the container /etc/crontabs/root
CRON_TIME Cronjob format "Minute Hour Day_of_month Month_of_year Day_of_week Year" 0 5 * * *
DELETE_AFTER Delete old backups after X many days. Set to 0 to disable 0
TIMESTAMP Set to true to append timestamp to the backup file false
UID User ID to run the cron job with 100
GID Group ID to run the cron job with 100
HEALTHCHECK_URL Set a healthcheck url like https://hc-ping.com/xyz unset
LOG_LEVEL DEBUG, INFO, WARNING, ERROR, CRITICAL are supported INFO
LOG_DIR Path to the logfile folder inside the container /app/log
LOG_DIR_PERMISSIONS Sets the permissions of the logfile folder. Set to -1 to disable. 777
TZ Set the timezone inside the container 3 unset
VW_DATA_FOLDER 4 Set the location of the vaultwarden data folder inside the container /data
VW_DATABASE_URL 4 Set the location of the vaultwarden database file inside the container VW_DATA_FOLDER/db.sqlite3
VW_ATTACHMENTS_FOLDER 4 Set the location of the vaultwarden attachments folder inside the container $VW_DATA_FOLDER/attachments
VW_ICON_CACHE_FOLDER 4 Set the location of the vaultwarden icon cache folder inside the container $VW_DATA_FOLDER/icon_cache

FAQ

I get an error like "unable to open database file"

Error: unable to open database file is most likely caused by permission errors. Note that sqlite3 creates a lock file in the source directory while running the backup. So source AND destination have to be +rw for the user. You can set the user and group ID via the UID and GID environment variables like described above.

Database is locked

Error: database is locked is most likely caused by choosing a backup location that is not on the same filesystem as the vaultwarden database (like a network filesystem).

Vaultwarden, when started with default settings, uses WAL (write-ahed logging). You can verify this by looking for a db.sqlite3-wal file in the same folder as your original database file. According to the official SQLite docs WAL will cause issues in network share scenarios (see https://www.sqlite.org/wal.html):

All processes using a database must be on the same host computer; WAL does not work over a network filesystem.

Basically there are two workarounds for this issue

  1. Choose a local target for your backup and then use some other tool like cp or rsync to copy the backup file to your network filesystem.
  2. Disable WAL in Vaultwarden. You can find a guide here (https://github.com/dani-garcia/vaultwarden/wiki/Running-without-WAL-enabled).

Date Time issues / Wrong timestamp

If you need timestamps in your local timezone you should mount /etc/timezone:/etc/timezone:ro and /etc/localtime:/etc/localtime:ro like it's done in the docker-compose.yml. An other possible solution is to set the environment variable accordingly (like TZ=Europe/Berlin) (see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for more information).

Attention if you are on an ARM based platform please note that alpine is used as base image for this project to keep things small. Since alpine 3.13 and above it's possible that you will end up with a container with broken time and date settings (i.e. year 1900). This is a known problem in the alpine project (see Github issue and solution) and there is nothing I can do about it. However in the alpine wiki a solution is being proposed which I also tested tested on my raspberry pi. After following the described process it started working again as expected. If you still experience issues or could for some reason not apply the aforementioned fixes please feel free to open an issue.

Why is the container started by the root user?

The main reason to build this image was to allow users to run sheduled tasks where their host OS does not allow them to do so, or where they want a "portable" way of using a scheduled tasks without relying on host OS mechanisms.

Since crond must be run as root user there is no way to start this container as a non-root user while using cron. I'm aware that there are other task schedulers like supercronic which allow to run without root privileges but I want to stay with the standard and established cron system for the time being.

Why sh is used instead of bash

Alpine by default comes without bash installed. Since the pre-installed ash shell is suitable for the tasks of this image and comes with no need to install additional tools like bash, /bin/sh is used as shell. The scripts also aims to be POSIX compliant which should make a switch of the base image fairly easy, if needed.

Footnotes

  1. See https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault for more details 2 3 4 5 6

  2. The permissions should at least be 700 since the backup folder itself gets the same permissions and with 600 it would not be accessible.

  3. see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for more information

  4. See https://github.com/dani-garcia/vaultwarden/wiki/Changing-persistent-data-location for more details 2 3 4