Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
language: generic
jobs:
include:
- script: 'shellcheck script.sh'
44 changes: 24 additions & 20 deletions README.MD
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
[Bash]FTP Backup Script
======================

A small script to upload backup tar to an external FTP server
# [Bash] Backup Script
[![Build Status](https://travis-ci.org/Pe46dro/Bash-FTP-Backup-Script.svg?branch=master)](https://travis-ci.org/Pe46dro/Bash-FTP-Backup-Script) [![Beerpay](https://img.shields.io/beerpay/hashdog/scrapfy-chrome-extension.svg)](https://beerpay.io/Pe46dro/Bash-FTP-Backup-Script)

How it works:
* You need to change "USERNAME,PASSWORD,SERVER" with information of your server
* You need to change "DIR" with absolute position of folder/file you want backup
* You need to change "FILE" with results of compression
A small script to backup a compressed folder to an external storage

If you have some problem open an issues on GitHub

##FAQ;

* Q: How can I make backups automatic?
### Prerequisites
Here you find the software that you need to install to have the function working
* cURL (Telegram notifications)
* mailx (Email notifications)
* Rclone (Rclone backup)

A: You can use crontab (on linux) [link](http://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/)
## How it works:
* Clone the repository `git clone https://github.com/Pe46dro/Bash-FTP-Backup-Script.git` or download script.sh `wget https://github.com/Pe46dro/Bash-FTP-Backup-Script/blob/master/script.sh`
* Open script.sh with your favorite text editor `vim script.sh`
* Customize the configuration and save
* Run `bash script.sh`

If you have some problem open an issues on GitHub

* Q: Why can't I start the script?
## FAQ

A: Make the file executable (chmod -x script.sh)
* Q: How can I make backups automatic?

A: Yes, you can use [crontab](http://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/)

# Contributors
| [<img src="https://www.gravatar.com/avatar/35923b3b04e23bef801553656b606bfag?s=100" alt="" height="100">](https://github.com/Pe46dro) |
|--|
| [Pe46dro](https://github.com/Pe46dro) |

* Q: Will this work on all linux distros?

A: This script was tested on Ubuntu 12/14,Debian and Centos 6 and has worked whitout any problems

* Q: Why SFTP don't work?
## License

A: You need to install "sshpass" ( apt-get install sshpass )
This project is licensed under the GNU General Public License v3.0 License - see the [LICENSE.md](LICENSE.md) file for details
298 changes: 253 additions & 45 deletions script.sh
Original file line number Diff line number Diff line change
@@ -1,65 +1,273 @@
#!/bin/sh
#!/usr/bin/env bash

# Linux FTP Backup Script
# Version: 1.0
# Script by: Pietro Marangon
# Skype: pe46dro
# Email: pietro.marangon@gmail.com
# Linux Simple Backup Script

clean_backup() {
rm -f ./$FILE
echo 'Local Backup Removed'
}
#
# Configuration
#

########################
# Edit Below This Line #
########################
# Backup Information
FILE="BACKUP_NAME" #Filename of backup file to be transfered (string)
EXT="zip" #Possbile value: zip,tar (string)
DIR="/var/www" #Directory where thing to backup is located (string)
EXCLUSION=("/var/www/**/node_modules" "/var/www/**/vendor") #Directory to exclude (array space separeted)
CHECKSUM=true #Generate backup checksum (true|false)
ROTATION=30 #How many day keep for better rotation use RClone (int|false)
LOG_FILE="/dev/null" #Log file location (string|/dev/null)
TMP_FOLDER="/tmp/" #Temp folder for archive generation

# FTP Login Data
USERNAME="USERNAME HERE"
PASSWORD="PASSWORD HERE"
SERVER="IP HERE"
PORT="REMOTE SERVER PORT"
#Encryption Information (only zip)
ENCRYPTION=false #Encryption (true|false)
ENCRYPTION_RANDOM=false #Random key generation (true|false) (Require notification enable)
ENCRYPTION_KEY="./my_super_secret_backup.key" #Encryption key (absolute path to file with key)

#Directory where thing to backup is located
DIR="/root"
#Notifications information
NOTIFICATION=false #Notifications (true|false)
SEND_LOG=false #Send log file (true|false)

#Remote directory where the backup will be placed
REMOTEDIR="./"
#Notifications Type
#1= Telegram Bot
#2= FUTURE USE
NOTIFICATION_TYPE=(1) #Multiple notifications support (array space separeted)

#Filename of backup file to be transfered DON'T WRITE EXTENSION (.tar/.zip/ecc...)
FILE="BACKUP_NAME"
TELEGRAM_KEY="YOUR_TELEGRAM_BOT_KEY" #Multiple notifications support (string)
TELEGRAM_CHAT=(1) #Multiple recipient support (array space separeted)

#Transfer type
#1=FTP
#2=SFTP
TYPE=1
#2=Rclone https://rclone.org/
TYPE=(1 2) #Multiple destinations support (array space separeted)

##############################
# Don't Edit Below This Line #
##############################
# FTP(s) Login Data
USERNAME="USERNAME HERE" #Login username (string)
PASSWORD="PASSWORD HERE" #Login password (string)
SERVER="IP HERE" #Remote server address (string)
PORT="REMOTE SERVER PORT" #Remote server port (string)
REMOTEDIR="./" #Remote server port (string)

d=$(date --iso)
# RClone Configuration
RCLONE_PATH="/usr/local/bin" #RClone binary folder (string)
RCLONE_REMOTE=("DEST1:/" "DEST2:/") #Rclone destinations (array space separeted)

FILE=$FILE"_"$d".tar.gz"
tar -czvf ./$FILE $DIR
echo 'Tar Complete'
# Task Configuration
BEFORE_COMMAND=false #Command to run before backup start (string|false)
AFTER_COMMAND=false #Command to run after backup finish (string|false)

if [ $TYPE -eq 1 ]
then
ftp -n -i $SERVER $PORT <<EOF
user $USERNAME $PASSWORD
binary
put $FILE $REMOTEDIR/$FILE
quit
#
# Functions
#

check_configuration() {
if [ "$ENCRYPTION" = true ] && [ "$ENCRYPTION_RANDOM" = false ]
then
if [ ! -f "$ENCRYPTION_KEY" ]
then
echo "Key file not found!" | tee -a --output-error=warn "$LOG_FILE"
exit 1
fi

if [ "$(stat -c %A "$ENCRYPTION_KEY")" != "-rw-------" ]
then
echo "WARNING: UNPROTECTED PRIVATE KEY FILE!" | tee -a --output-error=warn "$LOG_FILE"
echo "Permissions for '$ENCRYPTION_KEY' are too open. It is recommended that your private key files are NOT accessible by others." | tee -a --output-error=warn "$LOG_FILE"
exit 1
fi

fi
if [ "$ENCRYPTION" = true ] && [ "$ENCRYPTION_RANDOM" = true ] && [ "$NOTIFICATION" = false ]
then
echo "Random key require notification" | tee -a --output-error=warn "$LOG_FILE"
fi
}

generate_file_name() {
if [ "$ROTATION" != false ]
then
d=$(date --date="-$ROTATION day" '+%Y-%m-%d_%H')
RFILE="$FILE""_$d.$EXT"
fi
d=$(date '+%Y-%m-%d_%H')
FILE="$FILE""_$d.$EXT"
}

generate_key(){
KEY=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | fold -w 32 | head -n 1)
}

read_key(){
KEY=$(cat "$ENCRYPTION_KEY")
}

generate_backup(){

if [ "$EXT" = "tar" ]
then
for EXL in "${EXCLUSION[@]}"
do
PARAMS="$PARAMS --exclude='$EXL' "
done

tar -czvf "$TMP_FOLDER$FILE" "$DIR" | tee -a "$LOG_FILE"
echo 'Tar Complete' | tee -a "$LOG_FILE"
elif [ "$EXT" = "zip" ]
then

if [ "$ENCRYPTION" = true ] && [ "$NOTIFICATION" = true ]
then
PARAMS="-P $KEY"
fi

for EXL in "${EXCLUSION[@]}"
do
echo "Excluding '$EXL'"
PARAMS="$PARAMS --exclude '$EXL'"
done

PARAMS="$PARAMS -r $TMP_FOLDER$FILE $DIR"

local CMD="zip $PARAMS"

eval "$CMD" | tee -a "$LOG_FILE"
echo 'Zip Complete' | tee -a "$LOG_FILE"
fi

}

ftp_upload(){
ftp -n -i "$SERVER" "$PORT" <<EOF
user "$USERNAME" "$PASSWORD"
binary
put "$TMP_FOLDER$FILE" "$REMOTEDIR"/"$FILE"
quit
EOF
elif [ $TYPE -eq 2 ]
}

ftp_rotation(){
ftp -n -i "$SERVER" "$PORT" <<EOF
user "$USERNAME" "$PASSWORD"
binary
cd "$REMOTEDIR"
delete "$RFILE"
quit
EOF
}

rclone_upload () {
# $1 RClone remote
"$RCLONE_PATH"/rclone copy "$TMP_FOLDER$FILE" "$1"

}

rclone_rotation () {
# $1 RClone remote
"$RCLONE_PATH"/rclone delete "$1" --min-age "$ROTATION"d
}

generate_checksum(){
echo "MD5 HASH"
md5sum "$TMP_FOLDER$FILE" | tee -a "$LOG_FILE"
}

telegram_notification(){
# $1 Chat id
if [ "$SEND_LOG" = true ]
then
curl -F chat_id="$1" -F document=@"$LOG_FILE" https://api.telegram.org/bot"$TELEGRAM_KEY"/sendDocument
fi

if [ "$ENCRYPTION" = true ] && [ "$ENCRYPTION_RANDOM" = true ]
then
curl -s -X POST https://api.telegram.org/bot"$TELEGRAM_KEY"/sendMessage -d chat_id="$1" -d text="Key: $KEY"
fi
}

clean_backup() {
rm -f "$TMP_FOLDER$FILE"
echo 'Local Backup Removed' | tee -a "$LOG_FILE"
}

#
# Here be dragons
#

check_configuration

echo "###########################################" | tee -a "$LOG_FILE"
echo "Starting backup $FILE" | tee -a "$LOG_FILE"
echo "###########################################" | tee -a "$LOG_FILE"

if [ "$BEFORE_COMMAND" != false ]
then
rsync --rsh="sshpass -p $PASSWORD ssh -p $PORT -o StrictHostKeyChecking=no -l $USERNAME" $FILE $SERVER:$REMOTEDIR
else
echo 'Please select a valid type'
# shellcheck disable=SC2091
$($BEFORE_COMMAND)
fi

echo 'Remote Backup Complete'
generate_file_name

if [ "$ENCRYPTION" = true ] && [ "$ENCRYPTION_RANDOM" = true ]
then
generate_key
elif [ "$ENCRYPTION" = true ]
then
read_key
fi

generate_backup

for operation in "${TYPE[@]}"
do
if [ "$operation" -eq 1 ]
then
ftp_upload
if [ "$ROTATION" != false ]
then
ftp_rotation
fi
elif [ "$operation" -eq 2 ]
then
for rclone_destination in "${RCLONE_REMOTE[@]}"
do
rclone_upload "$rclone_destination"
if [ "$ROTATION" != false ]
then
rclone_rotation "$rclone_destination"
fi
done
else
echo "$operation is not a valid backup type option" | tee -a "$LOG_FILE"
fi
done

if [ "$CHECKSUM" = true ]
then
generate_checksum
fi

if [ "$NOTIFICATION" = true ]
then
for notification_operation in "${NOTIFICATION_TYPE[@]}"
do
if [ "$notification_operation" -eq 1 ]
then
for chat_id in "${TELEGRAM_CHAT[@]}"
do
telegram_notification "$chat_id"
done
fi
done
fi

echo 'Remote Backup Complete' | tee -a "$LOG_FILE"
clean_backup

if [ "$AFTER_COMMAND" != false ]
then
# shellcheck disable=SC2091
$($AFTER_COMMAND)
fi

echo "###########################################" | tee -a "$LOG_FILE"
echo "Ending backup $FILE" | tee -a "$LOG_FILE"
echo "###########################################" | tee -a "$LOG_FILE"

#END