Backup script and docs finetuning (#655)

* Remove restore directory after restore

* Backup bitcoin folder, excluding blocks and chainstate

* Deprecate and warn about the old backup process

* Update log messages

* Add backup documentation
This commit is contained in:
d11n 2022-06-06 08:11:09 +02:00 committed by GitHub
parent c176745bc3
commit 384f4883b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 221 additions and 34 deletions

View File

@ -499,6 +499,14 @@ Yes. Please [see the documentation](https://docs.btcpayserver.org/FAQ/FAQ-Deploy
## How can I back up my BTCPay Server?
See the [Backup & Restore](https://docs.btcpayserver.org/Deployment/BackupRestore/) guide in our documentation.
<details>
<summary>For backwards compatibility: Click here for the description of the old backup.sh process</summary>
:::warning
Please consider switching to the [new Backup & Restore process](https://docs.btcpayserver.org/Deployment/BackupRestore/), because the `backup.sh` will not be maintained anymore.
:::
We provide a backup script that dumps the database and saves the important files:
```bash
@ -509,9 +517,9 @@ cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
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).
* `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"
@ -533,6 +541,7 @@ This option does not need to stop and restart the docker-containers:
cd "$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
./backup.sh --only-db
```
</details>
## How can I connect to the database?

View File

@ -35,7 +35,7 @@ cd $btcpay_dir
dbcontainer=$(docker ps -a -q -f "name=postgres_1")
if [ -z "$dbcontainer" ]; then
printf "\n"
echo " Database container is not up and running. Starting BTCPay Server …"
echo " Database container is not up and running. Starting BTCPay Server …"
docker volume create generated_postgres_datadir
docker-compose -f $BTCPAY_DOCKER_COMPOSE up -d postgres
@ -48,7 +48,7 @@ if [ -z "$dbcontainer" ]; then
fi
printf "\n"
echo " Dumping database …"
echo " Dumping database …"
{
docker exec $dbcontainer pg_dumpall -c -U postgres | gzip > $dbdump_path
echo "✅ Database dump done."
@ -57,18 +57,22 @@ echo " Dumping database …"
exit 1
}
printf "\n Stopping BTCPay Server …\n\n"
printf "\n Stopping BTCPay Server …\n\n"
btcpay_down
printf "\n"
cd $docker_dir
echo " Archiving files in $(pwd)"
echo " Archiving files in $(pwd)"
{
tar \
--exclude="volumes/backup_datadir" \
--exclude="volumes/generated_bitcoin_datadir" \
--exclude="volumes/generated_litecoin_datadir" \
--exclude="volumes/generated_bitcoin_datadir/blocks" \
--exclude="volumes/generated_bitcoin_datadir/chainstate" \
--exclude="volumes/generated_bitcoin_datadir/debug.log" \
--exclude="volumes/generated_litecoin_datadir/blocks" \
--exclude="volumes/generated_litecoin_datadir/chainstate" \
--exclude="volumes/generated_litecoin_datadir/debug.log" \
--exclude="volumes/generated_postgres_datadir" \
--exclude="volumes/generated_clightning_bitcoin_datadir/_data/lightning-rpc" \
--exclude="**/logs/*" \
@ -92,18 +96,18 @@ echo " Archiving files in $(pwd)…"
}
fi
} || {
echo "🚨 Archiving failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
echo "🚨 Archiving failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
exit 1
}
printf "\n Restarting BTCPay Server …\n\n"
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
printf "\n Cleaning up …\n\n"
printf "\n Cleaning up …\n\n"
rm $dbdump_path
printf "✅ Backup done => $backup_path\n\n"

View File

@ -4,13 +4,13 @@ set -o pipefail -o errexit
if [ "$(id -u)" != "0" ]; then
printf "\n🚨 This script must be run as root.\n"
printf "➡️ Use the command 'sudo su -' (include the trailing hypen) and try again.\n\n"
printf "➡️ Use the command 'sudo su -' (include the trailing hypen) and try again.\n\n"
exit 1
fi
backup_path=$1
if [ -z "$backup_path" ]; then
printf "\n Usage: btcpay-restore.sh /path/to/backup.tar.gz\n\n"
printf "\n Usage: btcpay-restore.sh /path/to/backup.tar.gz\n\n"
exit 1
fi
@ -21,7 +21,7 @@ fi
if [[ "$backup_path" == *.gpg && -z "$BTCPAY_BACKUP_PASSPHRASE" ]]; then
printf "\n🔐 $backup_path is encrypted. Please provide the passphrase to decrypt it."
printf "\n Usage: BTCPAY_BACKUP_PASSPHRASE=t0pSeCrEt btcpay-restore.sh /path/to/backup.tar.gz.gpg\n\n"
printf "\n Usage: BTCPAY_BACKUP_PASSPHRASE=t0pSeCrEt btcpay-restore.sh /path/to/backup.tar.gz.gpg\n\n"
exit 1
fi
@ -32,7 +32,7 @@ dbdump_name=postgres.sql.gz
btcpay_dir="$BTCPAY_BASE_DIRECTORY/btcpayserver-docker"
# ensure clean restore dir
printf "\n Cleaning restore directory $restore_dir …\n\n"
printf "\n Cleaning restore directory $restore_dir …\n\n"
rm -rf $restore_dir
mkdir -p $restore_dir
@ -43,14 +43,14 @@ if [[ "$backup_path" == *.gpg ]]; then
backup_path="${backup_path%.*}"
printf "✅ Decryption done.\n\n"
} || {
echo "🚨 Decryption failed. Please check the error message above."
echo "🚨 Decryption failed. Please check the error message above."
exit 1
}
fi
cd $restore_dir
echo " Extracting files in $(pwd)"
echo " Extracting files in $(pwd)"
tar -xvf $backup_path -C $restore_dir
# basic control checks
@ -67,13 +67,13 @@ fi
cd $btcpay_dir
. helpers.sh
printf "\n Stopping BTCPay Server …\n\n"
printf "\n Stopping BTCPay Server …\n\n"
btcpay_down
cd $restore_dir
{
printf "\n Restoring volumes …\n"
printf "\n Restoring volumes …\n"
# ensure volumes dir exists
if [ ! -d "$docker_dir/volumes" ]; then
mkdir -p $docker_dir/volumes
@ -81,33 +81,31 @@ cd $restore_dir
# copy volume directories over
cp -r volumes/* $docker_dir/volumes/
# ensure datadirs excluded in backup exist
mkdir -p $docker_dir/volumes/generated_bitcoin_datadir/_data
mkdir -p $docker_dir/volumes/generated_litecoin_datadir/_data
mkdir -p $docker_dir/volumes/generated_postgres_datadir/_data
echo "✅ Volume restore done."
} || {
echo "🚨 Restoring volumes failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
exit 1
}
{
printf "\n Starting database container …\n"
printf "\n Starting database container …\n"
docker-compose -f $BTCPAY_DOCKER_COMPOSE up -d postgres
sleep 10
dbcontainer=$(docker ps -a -q -f "name=postgres")
if [ -z "$dbcontainer" ]; then
echo "🚨 Database container could not be started or found."
printf "\n Restarting BTCPay Server …\n\n"
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
exit 1
fi
} || {
echo "🚨 Starting database container failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
echo "🚨 Starting database container failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
exit 1
@ -116,23 +114,22 @@ cd $restore_dir
cd $restore_dir
{
printf "\n Restoring database …"
printf "\n Restoring database …"
gunzip -c $dbdump_name | docker exec -i $dbcontainer psql -U postgres postgres -a
echo "✅ Database restore done."
} || {
echo "🚨 Restoring database failed. Please check the error message above."
echo "🚨 Restoring database failed. Please check the error message above."
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
exit 1
}
printf "\n Restarting BTCPay Server …\n\n"
printf "\n Restarting BTCPay Server …\n\n"
cd $btcpay_dir
btcpay_up
printf "\n Cleaning up …\n\n"
# rm -rf $restore_dir
# rm -rf $backup_path $backup_path.gpg
printf "\n Cleaning up …\n\n"
rm -rf $restore_dir
printf "✅ Restore done\n\n"

177
docs/backup-restore.md Normal file
View File

@ -0,0 +1,177 @@
# Backup & Restore
This guide gets you up to speed with the [Docker deployment](../Docker/)'s Backup & Restore process.
You will learn about what to keep in mind when doing a backup and how to restore a backup.
[[toc]]
## Remarks and Considerations
The original backups strategy in BTCPay Server still exists and can be found [here](https://docs.btcpayserver.org/Docker/#how-can-i-back-up-my-btcpay-server).
While this documentation covers the [new process](https://github.com/btcpayserver/btcpayserver-docker/pull/641), the old `backup.sh` script still works.
:::warning
BTCPay Server is and will never be responsible for your backup.
Please make sure the backup includes the files and data you want to store.
Also, test the restore process before starting to rely on it.
:::
### Lightning channel backup
Please be aware of this important issue:
Old Lightning channel state is toxic!
You can lose all your funds if you close a channel based on an outdated state — and the state changes often!
If you publish an old state (say from yesterday's backup), you will most likely lose all your funds in the channel because the counterparty might publish a [revocation transaction](https://www.d11n.net/lightning-network-payment-channel-lifecycle.html#what-happens-in-case-of-a-false-close%3F)!
There is a high chance of failure in a disaster recovery scenario, where you may do a backup once per night and need to restore that one backup.
The Lightning channel backup from the `btcpay-backup.sh` script will be sufficient in a migration case, where the shutdown of the old server happens cleanly.
The old server should not be started after the restoration and start of the new server.
:::tip
The Lightning static channel backup should be watched by a script and copied over to a remote server to ensure you always have the latest state available.
We will provide such a script with a future update.
For now, keep the above in mind when restoring from the backup!
:::
## How does the backup work?
The backup process is run with the `btcpay-backup.sh` script.
Log in to your server, switch to the `root` user and type the following:
```bash
# The backup script needs to be run as the root user
sudo su -
# As the other scripts, it is inside the BTCPay base directory
cd $BTCPAY_BASE_DIRECTORY
./btcpay-backup.sh
```
The backup process needs to be run as `root`.
It will check for and let you know if you have to switch users.
The script will do the following steps:
* Ensure the database container is running
* Make a dump of the database
* Stop BTCPay Server
* Archive the Docker volumes and database dump
* Excluding the blockchains `blocks` and `chainstate` directories
* Optional: [Encrypt the archive](#set-a-backup-passphrase)
* Restart BTCPay Server
* Cleanup: Remove temporary files like the database dump
If the backup directory doesn't exist yet, the script will create it.
With these preparations taken, the backup process is now starting.
The script has checks to ensure it either works or fails with a comprehensive error message at every step of the way.
If there are errors, you will be notified like this:
```
🚨 Database container could not be started or found.
```
If everything works smoothly, you will see multiple completed marks in your console.
Whenever the backup has completed successfully, it will state:
```
✅ Backup done => /var/lib/docker/volumes/backup_datadir/_data/backup.tar.gz
```
Your BTCPay Server has now finished the backup process.
You must store these backups safely, for instance, by copying them to a remote server.
After making a backup the first time, it is always wise to at least test your backup in a restore scenario.
We will go over the extra options you can set with your backup in the next topic.
### Set a backup passphrase
You can set the `BTCPAY_BACKUP_PASSPHRASE` environment variable for encrypting the backup.
This passphrase will be used by the backup and restore scripts to encrypt and decrypt the backup file.
For the backup script, this would look like the following:
```bash
# Set the passphrase without adding it to the shell history
read -s -p "Enter passphrase: " BTCPAY_BACKUP_PASSPHRASE
export BTCPAY_BACKUP_PASSPHRASE
./btcpay-backup.sh
```
This `BTCPAY_BACKUP_PASSPHRASE` if set, is necessary to be in the [restore process](#how-to-restore) as well.
### Automation by crontab
Here is an example of a crontab script that does a nightly backup at 4:15 AM:
```
SHELL=/bin/bash
PATH=/bin:/usr/sbin:/usr/bin:/usr/local/bin
15 4 * * * /root/btcpayserver-docker/btcpay-backup.sh >/dev/null 2>&1
```
You need to set the right `SHELL` and `PATH`, so that the script can run with the correct context.
You might also want to set the `BTCPAY_BACKUP_PASSPHRASE` environment variable.
## How to restore?
It's very similar to the `btcpay-backup.sh` process but in reverse.
The `btcpay-restore.sh` script needs to be run with the path to your `backup.tar.gz` file.
First off, open a terminal and type the following as root.
Remember that if you set `BTCPAY_BACKUP_PASSPHRASE` on the backup, you also need to provide it for decryption :
```bash
# The restore script needs to be run as the root user
sudo su -
# As the other scripts, it is inside the BTCPay base directory
cd $BTCPAY_BASE_DIRECTORY
# Optional: Set the passphrase if you have used one for the backup
read -s -p "Enter passphrase: " BTCPAY_BACKUP_PASSPHRASE
export BTCPAY_BACKUP_PASSPHRASE
# Run the restore script with the full path to the backup file
./btcpay-restore.sh /var/backups/backup.tar.gz.gpg
```
The script will do the following steps:
* Extract (and decrypt) the backup archive
* Stop BTCPay Server
* Restore the Docker volumes
* Start the database container
* Import the database dump
* Restart BTCPay Server
* Cleanup: Remove the temporary restore directory
If the backup file cannot be found in the provided path, the script will exit with an error.
```
🚨 /var/backups/backup.tar.gz.gpg does not exist.
```
Just as the `btcpay-backup.sh` script, the restore will stop at ANY error it may encounter.
If the backup file was created while the `BTCPAY_BACKUP_PASSPHRASE` was set but not used on restoring, the following error would occur:
```
🚨 Decryption failed. Please check the error message above.
```
When the restore has completed, you get the message:
```
✅ Restore done
```
Everything should be up and running again when the restore is complete.
You've successfully restored your BTCPay Server. Congratulations!
:::tip
Always make sure your backup strategy is tested and fits your needs.
No one solution fits all, and we tried to cover the basic cases.
For the latest updates, always feel free to ask on the BTCPay Server community channels.
:::