dadatuputi/bitwarden_gcloud

Can not encrypt backup files.

crestcere opened this issue · 4 comments

Whenever I enable encryption using the BACKUP_ENCRYPTION_KEY variable, backup files aren't created and there are errors in the logs.
I think the problem is in the section of the backup script;
# If a password is provided, run it through openssl if [ -n "$BACKUP_ENCRYPTION_KEY" ]; then BACKUP_FILE=$BACKUP_FILE.aes256 tar -czf - -C $SQL_BACKUP_DIR $SQL_NAME -C $DATA $FILES | openssl enc -e -aes256 -salt -pbkdf2 -pass pass:${BACKUP_ENCRYPTION_KEY} -out $BACKUP_FILE else tar -czf $BACKUP_FILE -C $SQL_BACKUP_DIR $SQL_NAME -C $DATA $FILES fi

Here's the error log.

Backup file created at /data/backups/bw_backup_2023-09-08-141200.tar.gz.aes256
Running email backup
Email error: Can't stat /data/backups/bw_backup_2023-09-08-141200.tar.gz.aes256: No such file or directory
/data/backups/bw_backup_2023-09-08-141200.tar.gz.aes256: unable to attach file.

If I disable encryption key, it manages to take backup
Running backup to: email Backup file created at /data/backups/bw_backup_2023-09-08-142800.tar.gz Running email backup Sent e-mail (Bitwarden Backup (###@###.com) - bw_backup_2023-09-08-142800.tar.gz) to ###@###.com

Here is my .env file I redacted personal information

### GLOBAL VARIABLES ###

# The fully-qualified domain name for Bitwarden - what address do you want Bitwarden accessible? 
# Do not include the protocol (http/https), that is added when needed in docker-compose.yml
# Used for caddy proxy and ddns with Cloudflare
DOMAIN=###@###.com

# Timezone - used by some containers for logs / cron
# Find your location on this list and use the value in TZ Database Name, e.g Europe/Rome:
#   https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Europe/#####.###

# SMTP settings for Bitwarden and fail2ban 
# Uncomment and fill in details if you want to use e-mail invitations from bitwarden and e-mail alerts with fail2ban
# SMTP_SECURITY should be either starttls, force_tls, or off
# (see https://github.com/dani-garcia/vaultwarden/wiki/SMTP-Configuration)

SMTP_HOST=#####.###
SMTP_FROM=#####.###
SMTP_PORT=#####.###
SMTP_USERNAME=#####.###
SMTP_PASSWORD=#####.###
SMTP_SECURITY=#####.###
# For fail2ban, YES or NO
SMTP_TLS=#####.###
SMTP_AUTH_MECHANISM="Login"


### BITWARDEN VARIABLES ###

# Setting up Bitwarden for the first time can be done in two ways:
# Uncomment the method you want to use / comment the one you don't
# Method 1. [RECOMMENDED] because it avoids the admin page entirely; using the admin
#   page overrides these environmental variables which can cause confusion.
#   1. Set up your primary account(s) while SIGNUPS_ALLOWED=true
#   2. Set SIGNUPS_ALLOWED=false
#   3. Set the SMTP details above to enable e-mail invitation
#   4. Invite other users from within Bitwarden
#   Keep ADMIN_TOKEN blank to disable access to the admin page entirely.
SIGNUPS_ALLOWED=false
#ADMIN_TOKEN=
VAULTWARDEN_ADMIN_TOKEN=#####.###
# Method 2. Use the admin page to create your first user(s) then disable it.
#   1. Set ADMIN_TOKEN using gthe command `openssl rand -base64 48`
#   2. Use the admin page (/admin) to create your initial user(s).
#   3. Disable the admin page by clearing the token (ADMIN_TOKEN=)
#SIGNUPS_ALLOWED=false
#ADMIN_TOKEN=
# Note on ADMIN_TOKEN: https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page#secure-the-admin_token

## Enables push notifications (requires key and id from https://bitwarden.com/host)
# PUSH_ENABLED=true
PUSH_INSTALLATION_ID=#####.###
PUSH_INSTALLATION_KEY=#####.###
## Don't change this unless you know what you're doing.
# PUSH_RELAY_BASE_URI=https://push.bitwarden.com

# Specify YUBIKEY info if desired
#YUBICO_CLIENT_ID=
#YUBICO_SECRET_KEY=
#YUBICO_SERVER=

# Specfiy which user email addresses can create organizations
# Leave blank to allow all users
ORG_CREATION_USERS=sungerbob@proton.me

# Bitwarden Backup Options
#
#
# GENERAL OPTIONS:
#
# How often to run the backup script; default is daily at midnight
#BACKUP_SCHEDULE=0 0 * * *
BACKUP_SCHEDULE=*/2 * * * *
# How many days of backups to keep
BACKUP_DAYS=30
# Directory to place backups in (& sync from in rclone)
BACKUP_DIR=/data/backups
# Optional encryption key for backup
BACKUP_ENCRYPTION_KEY="test"
# Email address to send backup (BACKUP=email) or notifications (BACKUP_NOTIFY=true)
BACKUP_EMAIL_TO="#####.###"
# Send email notification for rclone|local backup jobs
BACKUP_EMAIL_NOTIFY=true
#
#
# Backup type is any combination of local|email|rclone - e.g., email,rclone
# If you use rclone, follow the instructions below
BACKUP=email
#
# RCLONE BACKUP OPTIONS:
#
# rclone first time run instructions:
#   1. Uncomment lines below and `docker-compose up -d`
#   2. With the backup container running, configure rclone with the following command:
#      `sudo docker exec -it backup ash -c 'rclone config --config $BACKUP_RCLONE_CONF'`
#   3. Follow the prompts and instructions at https://rclone.org/remote_setup/ - you 
#      will most likely need to download a rclone on another computer (it is portable)
#      to authorize.
#   4. The script should run as normal with a working configuration file
#BACKUP_RCLONE_CONF=/data/rclone/rclone.conf
#BACKUP_RCLONE_DEST=/bw_backup


### PROXY / CADDY VARIABLES ###

# EMAIL address to use with Let's Encrypt certificate provisioning
EMAIL=######@#####.###


### DDNS VARIABLES ###

# These variables are only necessary if you are using DDNS / comment them out if you don't use ddns
# Enter user id (use `id -u` to determine your user id)
#PUID=
# Enter group id (use `id -g` to determine your group id)
#PGID=


### COUNTRY BLOCKING VARIABLES ###

# Put any countries you want to block here using their ISO 3166-1 alpha-2 code (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
# Defaullt is China (CN), Hong Kong (HK), and Australia (AU) because gcloud free tier charges egress to those countries
# Data is pulled from www.ipdeny.com
COUNTRIES=CN HK AU

# How often to update the ip block list - default is daily at midnight; see https://en.wikipedia.org/wiki/Cron#CRON_expression
COUNTRYBLOCK_SCHEDULE=0 0 * * *


### WATCHTOWER VARIABLES ###

# How often should watchtower check for updated container images? Default is every Sunday at 3am
WATCHTOWER_SCHEDULE=0 0 3 ? * 0

I believe you might be using an older version of docker-compose.yml, I think you're using the built-in backup feature in the bitwarden container. Since a few months ago, the backup feature has been pulled out into its own docker image (https://github.com/dadatuputi/bwgc_backup). So, not running the latest version is probably accounting for some of your issues.

You did prompt me to look into the backup code and test the encryption function, and found a bug, so thanks for that.

I recommend that you pull the latest from the repo and skim the .env.template to make sure no breaking changes have happened since you last pulled.

You may have to update your BACKUP_RCLONE_CONF env var if you're using rclone (see https://github.com/dadatuputi/bitwarden_gcloud/wiki/Backup#troubleshooting-rclone-creation).

@dadatuputi I don't think I have an older version because I just found out about this project. I updated with docker-compose up -d but still got the same problem. I think I also have the openssl package.

Here is terminal log;


$ docker-compose up -d
	proxy is up-to-date
	bitwarden is up-to-date
	ddns is up-to-date
	fail2ban is up-to-date
	watchtower is up-to-date
	countryblock is up-to-date
	Recreating backup ... done
$ docker logs backup
	Removing any existing crontab entries for backup.sh
	Adding backup.sh crontab entry (*/2 * * * *)
	Starting the cron daemon
$ docker logs backup
	Removing any existing crontab entries for backup.sh
	Adding backup.sh crontab entry (*/2 * * * *)
	Starting the cron daemon
	Finished configuring email.
	Running backup to: email
	Backup file created at /data/backups/bw_backup_2023-09-08-162001.tar.gz.aes256
	Running email backup
	Email error: Can't stat /data/backups/bw_backup_2023-09-08-162001.tar.gz.aes256: No such file or directory
	/data/backups/bw_backup_2023-09-08-162001.tar.gz.aes256: unable to attach file.
$ openssl help
	Standard commands
	asn1parse         ca                ciphers           cms               
	crl               crl2pkcs7         dgst              dhparam           
	dsa               dsaparam          ec                ecparam           
	enc               engine            errstr            gendsa            
	genpkey           genrsa            help              list              
	nseq              ocsp              passwd            pkcs12            
	pkcs7             pkcs8             pkey              pkeyparam         
	pkeyutl           prime             rand              rehash            
	req               rsa               rsautl            s_client          
	s_server          s_time            sess_id           smime             
	speed             spkac             srp               storeutl          
	ts                verify            version           x509              

	Message Digest commands (see the `dgst' command for more details)
	blake2b512        blake2s256        gost              md4               
	md5               mdc2              rmd160            sha1              
	sha224            sha256            sha3-224          sha3-256          
	sha3-384          sha3-512          sha384            sha512            
	sha512-224        sha512-256        shake128          shake256          
	sm3               

	Cipher commands (see the `enc' command for more details)
	aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb       
	aes-256-cbc       aes-256-ecb       aria-128-cbc      aria-128-cfb      
	aria-128-cfb1     aria-128-cfb8     aria-128-ctr      aria-128-ecb      
	aria-128-ofb      aria-192-cbc      aria-192-cfb      aria-192-cfb1     
	aria-192-cfb8     aria-192-ctr      aria-192-ecb      aria-192-ofb      
	aria-256-cbc      aria-256-cfb      aria-256-cfb1     aria-256-cfb8     
	aria-256-ctr      aria-256-ecb      aria-256-ofb      base64            
	bf                bf-cbc            bf-cfb            bf-ecb            
	bf-ofb            camellia-128-cbc  camellia-128-ecb  camellia-192-cbc  
	camellia-192-ecb  camellia-256-cbc  camellia-256-ecb  cast              
	cast-cbc          cast5-cbc         cast5-cfb         cast5-ecb         
	cast5-ofb         des               des-cbc           des-cfb           
	des-ecb           des-ede           des-ede-cbc       des-ede-cfb       
	des-ede-ofb       des-ede3          des-ede3-cbc      des-ede3-cfb      
	des-ede3-ofb      des-ofb           des3              desx              
	idea              idea-cbc          idea-cfb          idea-ecb          
	idea-ofb          rc2               rc2-40-cbc        rc2-64-cbc        
	rc2-cbc           rc2-cfb           rc2-ecb           rc2-ofb           
	rc4               rc4-40            rc5               rc5-cbc           
	rc5-cfb           rc5-ecb           rc5-ofb           seed              
	seed-cbc          seed-cfb          seed-ecb          seed-ofb          
	sm4-cbc           sm4-cfb           sm4-ctr           sm4-ecb           
	sm4-ofb

Here is my docker.yml;


$ cat docker-compose.yml
	version: '3.4'

	x-logging: &default-logging
	  logging:
		driver: "json-file"
		options:
		  max-size: "10m"
		  max-file: "10"
		  compress: "true"

	services:
	  bitwarden:
		# Standard Bitwarden is very resource-heavy and cannot run on micro cloud instances
		# Vaultwarden is a Rust (mostly) feature-complete implementation of Bitwarden
		# https://github.com/dani-garcia/vaultwarden
		image: vaultwarden/server:alpine 
		restart: always
		container_name: bitwarden
		depends_on: 
		- proxy
		<<: *default-logging
		volumes:
		- ${PWD}/bitwarden:/data
		environment:
		- LOG_FILE=/data/bitwarden.log
		- SHOW_PASSWORD_HINT=false
		- DOMAIN=https://${DOMAIN}          # DOMAIN is set in .env but doesn't have protocol prefix
		- IP_HEADER=X-Forwarded-For
		- ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}                       # Value-less variables are set in .env
		- SIGNUPS_ALLOWED
		- SMTP_HOST
		- SMTP_FROM
		- SMTP_FROM_NAME=Bitwarden (${DOMAIN})
		- SMTP_PORT
		- SMTP_SECURITY
		- SMTP_USERNAME
		- SMTP_PASSWORD
		- PUSH_ENABLED
		- PUSH_INSTALLATION_ID
		- PUSH_INSTALLATION_KEY
		- YUBICO_CLIENT_ID
		- YUBICO_SECRET_KEY
		- YUBICO_SERVER
		- ORG_CREATION_USERS
		- TZ


	  backup:
		#build: ./docker/backup                                     # backup, in case container registry is not responsive
		image: ghcr.io/dadatuputi/bwgc_backup:master                # from https://github.com/dadatuputi/bwgc_backup
		restart: on-failure
		container_name: backup
		depends_on:
		- bitwarden
		<<: *default-logging
		volumes: 
		  - ${PWD}/bitwarden:/data:ro
		  - ${PWD}/bitwarden/rclone:/data/rclone 
		  - ${PWD}/bitwarden/backups:/data/backups 
		environment:
		- BACKUP                            # Value-less variables are set in .env
		- BACKUP_SCHEDULE
		- BACKUP_DAYS
		- BACKUP_DIR
		- BACKUP_ENCRYPTION_KEY
		- BACKUP_EMAIL_TO
		- BACKUP_EMAIL_NOTIFY
		- BACKUP_RCLONE_CONF
		- BACKUP_RCLONE_DEST
		- SMTP_HOST
		- SMTP_FROM
		- SMTP_FROM_NAME=Bitwarden Backup (${DOMAIN})
		- SMTP_PORT
		- SMTP_SECURITY
		- SMTP_USERNAME
		- SMTP_PASSWORD
		- TZ


	  proxy:
		# Caddy provides an automatic HTTPS reverse proxy with Let's Encrypt cert provisioning
		# Uses local Dockerfile to include tzdata package
		# https://caddyserver.com/
		#build: ./docker/proxy                              # backup, in case container registry is not responsive
		image: ghcr.io/dadatuputi/bwgc_caddy:master         # from https://github.com/dadatuputi/bwgc_proxy
		restart: always
		container_name: proxy
		<<: *default-logging
		volumes:
		- ${PWD}/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
		- ${PWD}/caddy/data:/data
		- caddycerts:/root/.caddy
		ports:
		- 80:80                             # Port 80 is necessary for Let's Encrypt ACME
		- 443:443
		environment:
		- ACME_AGREE=true                   # agree to ACME for auto HTTPS
		- DOMAIN                            # Value-less variables are set in .env
		- EMAIL
		- TZ


	  ddns:
		# This provides a ddclient dynamic dns updating cron which is as simple as running it
		# and editing the ddns/config/ddclient.conf file
		# https://github.com/linuxserver/docker-ddclient
		image: linuxserver/ddclient
		restart: always
		container_name: ddns
		<<: *default-logging
		depends_on: 
		- bitwarden
		volumes:
		- ${PWD}/ddns:/config
		environment:
		- PUID
		- PGID
		- TZ


	  fail2ban:
		# Implements fail2ban functionality, banning ips that 
		# try to bruteforce your vault
		# https://github.com/dani-garcia/vaultwarden/wiki/Fail2Ban-Setup
		# https://github.com/crazy-max/docker-fail2ban
		image: crazymax/fail2ban:latest
		restart: always
		container_name: fail2ban
		<<: *default-logging
		depends_on:
		- bitwarden
		volumes:
		- ${PWD}/fail2ban:/data
		- ${PWD}/bitwarden:/bitwarden:ro
		network_mode: "host"
		privileged: true
		cap_add:
		- NET_ADMIN
		- NET_RAW
		environment:
		- F2B_DB_PURGE_AGE=30d
		- F2B_LOG_TARGET=/data/fail2ban.log
		- F2B_LOG_LEVEL=INFO
		- F2B_IPTABLES_CHAIN=INPUT
		- SSMTP_HOST=${SMTP_HOST}
		- SSMTP_PORT=${SMTP_PORT}
		- SSMTP_USER=${SMTP_USERNAME}
		- SSMTP_PASSWORD=${SMTP_PASSWORD}
		- SSMTP_HOSTNAME=Bitwarden (${DOMAIN})
		- SSMTP_TLS=${SMTP_TLS}
		- SSMTP_STARTTLS=YES
		- TZ


	  countryblock:
		# The block script will block any country (defaults to CN and AU)
		# Requires cap_add as listed and privileged because it uses iptables and ipset
		# https://hub.docker.com/_/alpine/
		#build: ./docker/countryblock                       # backup, in case container registry is not responsive
		image: ghcr.io/dadatuputi/bwgc_countryblock:master  # from https://github.com/dadatuputi/bwgc_countryblock
		restart: always
		container_name: countryblock
		<<: *default-logging
		depends_on: 
		- bitwarden
		network_mode: "host"
		privileged: true
		cap_add:
		- NET_ADMIN
		- NET_RAW
		environment:
		- COUNTRIES
		- COUNTRYBLOCK_SCHEDULE
		- TZ


	  watchtower:
		# Watchtower will pull down your new image, gracefully shut down your existing container 
		# and restart it with the same options that were used when it was deployed initially
		# https://github.com/containrrr/watchtower
		image: containrrr/watchtower
		restart: always
		container_name: watchtower
		<<: *default-logging
		depends_on: 
		- bitwarden
		volumes:
		- /var/run/docker.sock:/var/run/docker.sock
		environment:
		- WATCHTOWER_CLEANUP=true
		- WATCHTOWER_SCHEDULE
		- TZ


	volumes:
	  caddycerts:

Oh, you are probably just running into the same error that I did, and fixed about an hour ago. Try a docker-compose pull and you should get the new backup image. Give that a try.

The wiki has some info about testing the backup feature: https://github.com/dadatuputi/bitwarden_gcloud/wiki/Backup#testing-backup

@dadatuputi It's working, thank you so much ❤️