diff --git a/README.md b/README.md index 1e08cab..29e4155 100644 --- a/README.md +++ b/README.md @@ -471,3 +471,40 @@ If you need to run on a different port, it's best to terminate SSL using another ## Can I offload HTTPS termination? Yes. Please [see the documentation](https://docs.btcpayserver.org/FAQ/FAQ-Deployment/#can-i-use-an-existing-nginx-server-as-a-reverse-proxy-with-ssl-termination). + +## How can I back up my BTCPay Server? + +We provide a backup script that dumps the database and saves the important files: + +```bash +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" +./backup.sh +``` + +This will save the backup locally as `/var/lib/docker/volumes/backup_datadir/_data/backup.tar.gz`. +These are the options to customize the backup name and location: + +- `BACKUP_TIMESTAMP=true` saves the backup with datetime as part of the file name, so that backups do not get overwritten. +- `BACKUP_PROVIDER=SCP` saves the backup remotely, requires additional `SCP_TARGET` environment variable (see below). +- `BACKUP_PROVIDER=Dropbox` saves the backup to Dropbox, requires additional `DROPBOX_TOKEN` environment variable (see below). + +```bash +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" + +# Backup with custom file name and timestamp: +BACKUP_TIMESTAMP=true ./backup.sh + +# Backup via SCP: +BACKUP_PROVIDER=SCP SCP_TARGET=myhost:backups/btcpay ./backup.sh + +# Backup to Dropbox: +BACKUP_PROVIDER=Dropbox DROPBOX_TOKEN=myDropboxToken ./backup.sh +``` + +You can also choose to only dump the database. +This option does not need to stop and restart the docker-containers: + +```bash +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" +./backup.sh --only-db +``` diff --git a/backup.sh b/backup.sh index c5d8ef2..aecc673 100755 --- a/backup.sh +++ b/backup.sh @@ -16,35 +16,84 @@ if [ "$(id -u)" != "0" ]; then exit 1 fi -(return 2>/dev/null) && sourced=1 || sourced=0 - -if [ $sourced != 1 ]; then - echo "You forgot the leading '.' followed by a space!" - echo "Try this format: . ./backup.sh" - exit 1 -fi - -if [ -z ${BACKUP_PROVIDER+x} ]; then - echo "Set BACKUP_PROVIDER environmental variable and try again." - exit 1 -elif [ ${BACKUP_PROVIDER="Dropbox"} ]; then - if [ -z ${DROPBOX_TOKEN+x} ]; then - echo "Set DROPBOX_TOKEN environmental variable and try again." +case "$BACKUP_PROVIDER" in + "Dropbox") + if [ -z "$DROPBOX_TOKEN" ]; then + echo "Set DROPBOX_TOKEN environment variable and try again." exit 1 fi - if [ -z ${1+x} ]; then - filename="backup.tar.gz" - else - filename=$1 - fi - if [ ! -d /var/lib/docker/volumes/backup_datadir ]; then - docker volume create backup_datadir - fi - btcpay-down.sh - tar --exclude='/var/lib/docker/volumes/backup_datadir/*' --exclude='/var/lib/docker/volumes/generated_bitcoin_datadir/*' --exclude='/var/lib/docker/volumes/generated_litecoin_datadir/*' -cvzf /var/lib/docker/volumes/backup_datadir/_data/${filename} /var/lib/docker/volumes - btcpay-up.sh - echo "Uploading to Dropbox..." - docker run --name backup --env DROPBOX_TOKEN=$DROPBOX_TOKEN -v backup_datadir:/data jvandrew/btcpay-dropbox:1.0.5 $filename - echo "Deleting local backup..." - rm /var/lib/docker/volumes/backup_datadir/_data/${filename} + ;; + + "SCP") + if [ -z "$SCP_TARGET" ]; then + echo "Set SCP_TARGET environment variable and try again." + exit 1 + fi + ;; + + *) + echo "No BACKUP_PROVIDER set. Backing up to local directory." + ;; +esac + +# preparation +volumes_dir=/var/lib/docker/volumes +backup_dir="$volumes_dir/backup_datadir" +filename="backup.tar.gz" +dumpname="postgres.sql" + +if [ "$BACKUP_TIMESTAMP" == true ]; then + timestamp=$(date "+%Y%m%d-%H%M%S") + filename="$timestamp-$filename" + dumpname="$timestamp-$dumpname" fi + +backup_path="$backup_dir/_data/${filename}" +dbdump_path="$backup_dir/_data/${dumpname}" + +cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker" +. helpers.sh + +# dump database +echo "Dumping database …" +btcpay_dump_db $dumpname + +if [[ "$1" == "--only-db" ]]; then + tar -cvzf $backup_path $dbdump_path +else + # stop docker containers, save files and restart + echo "Stopping BTCPay Server …" + btcpay_down + + echo "Backing up files …" + tar --exclude="$backup_dir/*" --exclude="$volumes_dir/generated_bitcoin_datadir/*" --exclude="$volumes_dir/generated_litecoin_datadir/*" --exclude="$volumes_dir/**/logs/*" -cvzf $backup_path $dbdump_path $volumes_dir + + echo "Restarting BTCPay Server …" + btcpay_up +fi + +# post processing +case $BACKUP_PROVIDER in + "Dropbox") + echo "Uploading to Dropbox …" + docker run --name backup --env DROPBOX_TOKEN=$DROPBOX_TOKEN -v backup_datadir:/data jvandrew/btcpay-dropbox:1.0.5 $filename + echo "Deleting local backup …" + rm $backup_path + ;; + + "SCP") + echo "Uploading via SCP …" + scp $backup_path $SCP_TARGET + echo "Deleting local backup …" + rm $backup_path + ;; + + *) + echo "Backed up to $backup_path" + ;; +esac + +# cleanup +rm $dbdump_path + +echo "Backup done." diff --git a/helpers.sh b/helpers.sh index 741a6a4..c471789 100755 --- a/helpers.sh +++ b/helpers.sh @@ -145,4 +145,16 @@ btcpay_restart() { docker-compose -f $BTCPAY_DOCKER_COMPOSE restart fi popd > /dev/null -} \ No newline at end of file +} + +btcpay_dump_db() { + pushd . > /dev/null + cd "$(dirname "$BTCPAY_ENV_FILE")" + backup_dir="/var/lib/docker/volumes/backup_datadir/_data" + if [ ! -d "$backup_dir" ]; then + docker volume create backup_datadir + fi + local filename=${1:-"postgres-$(date "+%Y%m%d-%H%M%S").sql"} + docker exec $(docker ps -a -q -f "name=postgres_1") pg_dumpall -c -U postgres > "$backup_dir/$filename" + popd > /dev/null +}