Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A script built off of @alexbosworth's backup script that monitors lnd's `channel.backup` file for changes and uploads those changes to Dropbox when detected.

Lnd Automated Channel Backup Guide

This script was inspired by @alexbosworth's channel.backup backup script and my own .lnd folder backup script. It monitors lnd's channel.backup file for changes and uploads those changes to Dropbox when detected.

Setup Script

To get started, download the script:

$ cd && wget -qN https://gist.githubusercontent.com/vindard/e0cd3d41bb403a823f3b5002488e3f90/raw/4bcf3c0163f77443a6f7c00caae0750b1fa0d63d/lnd-channel-backup.sh
$ sudo chmod +x lnd-channel-backup.sh

Setup Dropbox API Key

In your web browser, do the following:

  1. Go to https://www.dropbox.com/developers/apps/create and sign in

  2. Choose Dropbox Api

    Dropbox API 1

  3. Choose App Folder

    Dropbox API 2

  4. Name your app and click Create App to proceed

    Dropbox API 3

  5. On the settings page for your new app, scroll down to OAuth 2 and click Generate

    Dropbox API 4

  6. You will now see a string of letters and numbers appear. This is your Api Token. Copy this token and keep it safe for the next steps. This api token will be referenced as <dropbox-api-token> in the next step.

  7. Return to your terminal and run the following to insert the api token into the backup script:

    $ TOKEN=<dropbox-api-token>
    $ cd && sed -i "s/DROPBOX_APITOKEN=\".*\"/DROPBOX_APITOKEN=\"$TOKEN\"/" lnd-channel-backup.sh
    $ unset TOKEN
    

Setup script as systemd service

Create file: sudo nano /etc/systemd/system/backup-channels.service

Note: be sure to change the <user-here> value to your own home folder's name

[Service]
ExecStart=/home/<user-here>/lnd-channel-backup.sh
Restart=always
RestartSec=1
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=backup-channels
User=root
Group=root

[Install]
WantedBy=multi-user.target

Start

sudo systemctl start backup-channels

Monitor

journalctl -fu backup-channels

Run at boot

sudo systemctl enable backup-channels

#!/bin/bash
# SET DROPBOX API KEY FOR UPLOADS
DROPBOX_APITOKEN=""
# OPTIONAL SET A DEVICE NAME TO BE USED FOR BACKUPS (DEFAULTS TO /etc/hostname)
DEVICE=""
# INOTIFY CHECK
# --------------
install_inotify () {
sudo apt update
sudo apt install -y inotify-tools
}
inotifycheck () {
dpkg -s "inotify-tools" &> /dev/null
if [ ! $? -eq 0 ]; then
install_inotify
fi
}
# SETUP
# --------------
setup_files_and_folders () {
# Fetches the user whose home folder the directories will be stored under
ADMINUSER=( $(ls /home | grep -v bitcoin) )
if [ -z "$DEVICE" ] ; then
DEVICE=$(echo $(cat /etc/hostname))
fi
DEVICE=$(echo $DEVICE | awk '{print tolower($0)}' | sed -e 's/ /-/g')
# Setup folders and filenames
DATADIR=/home/bitcoin/.lnd
WORKINGDIR=/home/$ADMINUSER/lnd-data-backups
BACKUPFOLDER=.lndbackup-$DEVICE
# channel.backup file details
CHANFILEDIR=data/chain/bitcoin/mainnet
BACKUPFILE=channel.backup
SOURCEFILE=$DATADIR/$CHANFILEDIR/$BACKUPFILE
# Make sure necessary folders exist
if [[ ! -e ${WORKINGDIR} ]]; then
mkdir -p ${WORKINGDIR}
fi
cd ${WORKINGDIR}
if [[ ! -e ${BACKUPFOLDER} ]]; then
mkdir -p ${BACKUPFOLDER}
fi
cd ${BACKUPFOLDER}
}
# CHECKS
# --------------
online_check () {
wget -q --tries=10 --timeout=20 --spider http://google.com
if [[ $? -eq 0 ]]; then
ONLINE=true
else
ONLINE=false
fi
#echo "Online: "$ONLINE
}
dropbox_api_check () {
VALID_DROPBOX_APITOKEN=false
curl -s -X POST https://api.dropboxapi.com/2/users/get_current_account \
--header "Authorization: Bearer "$DROPBOX_APITOKEN | grep rror
if [[ ! $? -eq 0 ]] ; then
VALID_DROPBOX_APITOKEN=true
else
echo "Invalid Dropbox API Token!"
fi
}
dropbox_upload_check () {
UPLOAD_TO_DROPBOX=false
if [ ! -z $DROPBOX_APITOKEN ] ; then
online_check
if [ $ONLINE = true ] ; then
dropbox_api_check
else
echo "Please check that the internet is connected and try again."
fi
if [ $VALID_DROPBOX_APITOKEN = true ] ; then
UPLOAD_TO_DROPBOX=true
fi
fi
}
# UPLOAD
# --------------
upload_to_dropbox () {
FINISH=$(curl -s -X POST https://content.dropboxapi.com/2/files/upload \
--header "Authorization: Bearer "${DROPBOX_APITOKEN}"" \
--header "Dropbox-API-Arg: {\"path\": \"/"$BACKUPFOLDER"/"$1"\",\"mode\": \"overwrite\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}" \
--header "Content-Type: application/octet-stream" \
--data-binary @$1)
#echo $FINISH | jq .
UPLOADTIME=$(echo $FINISH | jq -r .server_modified)
if [ ! -z $UPLOADTIME ] ; then
echo "Successfully uploaded!"
else
echo "Unknown error when uploading..."
fi
}
# RUN CHECKS AND IF PASS, EXECUTE BACKUP TO DROPBOX
run_dropbox_backup () {
dropbox_upload_check
if [ $UPLOAD_TO_DROPBOX = true ] ; then
upload_to_dropbox $1
fi
}
##############
# RUN SCRIPT
##############
run_backup_on_change () {
echo "Copying backup file..."
cp $SOURCEFILE $BACKUPFILE
md5sum $SOURCEFILE > $BACKUPFILE.md5
sed -i 's/\/.*\///g' $BACKUPFILE.md5
echo
echo "Uploading backup file: '"${BACKUPFILE}"'..."
run_dropbox_backup $BACKUPFILE
echo "---"
echo "Uploading signature: '"${BACKUPFILE}.md5"'..."
run_dropbox_backup $BACKUPFILE.md5
}
run () {
inotifycheck
setup_files_and_folders
while true; do
inotifywait $SOURCEFILE
run_backup_on_change
echo
done
}
run
@giulnz

This comment has been minimized.

Copy link

giulnz commented Apr 18, 2019

Hi thanks usuful and clean work. Can i ask you what's md5 purpose ?
Is it for integrity check in case of restore ?
Also i don't understand what sed -i 's/\/.*\///g' do.

@vindard

This comment has been minimized.

Copy link
Owner Author

vindard commented Jun 4, 2019

Hey @giulnz, really sorry for the late reply! Yes the md5 is to attach a signature of the original file for any verification purposes. Can be checked when the file is moved off the device, or later on when the file is being restored.

That sed command I believe removes the filename from the string that's returned when md5sum $SOURCEFILE is run. If I remember correctly, it's to save just the md5 hash produced to the .md5 file and to remove any extra data that might have been added along.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.