Add dobapor script from helios
DOBAPOR - DumpOrBackupAndPruneOrRestore
This commit is contained in:
parent
041861f7b4
commit
8a9f082424
1 changed files with 457 additions and 0 deletions
457
aech/dobapor.sh
Normal file
457
aech/dobapor.sh
Normal file
|
@ -0,0 +1,457 @@
|
|||
#!/bin/bash
|
||||
# DOBAPOR - DumpOrBackupAndPruneOrRestore
|
||||
# (c) 2019 Tobias Strobel <git@strobeltobias.de>
|
||||
|
||||
DATEFORMAT='%Y-%m-%d-%H-%M-%S'
|
||||
BKPPATH='/root/backup'
|
||||
LOGPATH="${BKPPATH}/log"
|
||||
TMPDIR=$(mktemp -d)
|
||||
HOST=$(hostname)
|
||||
DOMAIN=$(hostname -d)
|
||||
ROOT_DIR='/opt'
|
||||
CONFIG_DIR="${ROOT_DIR}/config"
|
||||
DATA_DIR="${ROOT_DIR}/data"
|
||||
RUNTIME_DIR="${ROOT_DIR}/runtime"
|
||||
ACTIONS=( dump backup restore prune status )
|
||||
MCSERVICE='vmail|crypt|redis|rspamd|postfix|mysql'
|
||||
SERVICE='rootfs|etc'
|
||||
#DUMPSERVICE='nextcloud|wallabag|mailcow|ttrss|ejabberd'
|
||||
DUMPSERVICE='wallabag|mailcow|ejabberd'
|
||||
CHOOSESERVICE="${SERVICE}|${DUMPSERVICE}|all"
|
||||
CHOOSEMCSERVICE="${MCSERVICE}|all"
|
||||
DB_KEEPLATEST=4 # n+1
|
||||
LOGS_KEEPLATEST=11 # n+1
|
||||
#BORG_KEEPWITHIN=2d
|
||||
#BORG_KEEPDAILY=7
|
||||
#BORG_KEEPWEEKLY=4
|
||||
#BORG_KEEPMONTHLY=3
|
||||
BORG_KEEPWITHIN=1H
|
||||
BORG_KEEPDAILY=0
|
||||
BORG_KEEPWEEKLY=0
|
||||
BORG_KEEPMONTHLY=0
|
||||
declare -a BORG_REPOS
|
||||
declare -a BORG_PASSPHRASES
|
||||
BORG_REPOS[1]='/localbackup'
|
||||
BORG_PASSPHRASES[1]='truth plug charcoal spoils thank ladder chaperone scale playmate retiree'
|
||||
BORG_REPOS[2]='rsync.net:borg-aech'
|
||||
BORG_PASSPHRASES[2]='debtor snowcap protrude swinger doozy catchy frenzy shininess denote ferris'
|
||||
|
||||
# only for Rsync.net users
|
||||
export BORG_REMOTE_PATH=/usr/local/bin/borg1/borg1
|
||||
|
||||
if [[ ! ${1} =~ (dump|backup|restore|prune|status) ]]; then
|
||||
echo "First parameter needs to be 'dump|backup|restore|prune|status'"
|
||||
exit 1
|
||||
elif [[ ${1} =~ (backup|prune) && ! ${2} =~ (${CHOOSESERVICE}) ]]; then
|
||||
echo "Second parameter needs to be '${CHOOSESERVICE}'"
|
||||
exit 1
|
||||
elif [[ ${1} =~ (dump) && ! ${2} =~ (${DUMPSERVICE}) ]]; then
|
||||
echo "Second parameter needs to be '${DUMPSERVICE}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ACTION=${1}
|
||||
if [ ! -d "${BKPPATH}" ]; then
|
||||
mkdir -p ${BKPPATH}
|
||||
fi
|
||||
if [ ! -d "${LOGPATH}" ]; then
|
||||
mkdir -p ${LOGPATH}
|
||||
fi
|
||||
LOGFILE="${LOGPATH}/${ACTION}-$(date +${DATEFORMAT}).log"
|
||||
|
||||
## FUNCTIONS ###################################################
|
||||
|
||||
function dumpDBfromDocker() {
|
||||
|
||||
if [[ ! ${1} =~ (mysql|postgres) ]]; then
|
||||
echo 'First parameter needs to be mysql or postgres.'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ${1} =~ (postgres) ]] && [[ ! ${2} =~ (nextcloud|wallabag|ttrss|ejabberd) ]]; then
|
||||
echo 'Second parameter needs to be nextcloud, wallabag, ttrss or ejabberd.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "${DATA_DIR}/${2}/dumps"
|
||||
chmod 700 -R "${DATA_DIR}/${2}/dumps"
|
||||
|
||||
echo "Dump ${1} database of ${2}..."
|
||||
case "${1}" in
|
||||
mysql)
|
||||
if [[ ! -f ${CONFIG_DIR}/${2}/${2}.env ]]; then
|
||||
echo "No env file for ${2} found!"
|
||||
exit 1
|
||||
fi
|
||||
source ${CONFIG_DIR}/${2}/${2}.env
|
||||
SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' ${CONFIG_DIR}/${2}/docker-compose.yml|head -n1)
|
||||
docker run --rm \
|
||||
--network $(docker network ls -qf name=${2}_internal) \
|
||||
-v ${RUNTIME_DIR}/${2}/db:/var/lib/mysql/ \
|
||||
--entrypoint= \
|
||||
-v ${DATA_DIR}/${2}/dumps:/dump \
|
||||
${SQLIMAGE} /bin/sh -c "mysqldump -h${MYSQL_HOST:-db} -u${MYSQL_USER:-${2}} -p${MYSQL_PASSWORD} --all-databases --single-transaction --quick|gzip -c >/dump/mysql-$(date +${DATEFORMAT}).gz; \
|
||||
ls -tp /dump/mysql*| grep -v '/$' | tail -n +${DB_KEEPLATEST:-4} | xargs -d '\n' -r rm --"
|
||||
check $?
|
||||
;;&
|
||||
postgres)
|
||||
if [[ ! -f ${CONFIG_DIR}/${2}/${2}.env ]]; then
|
||||
echo "No env file for ${2} found!"
|
||||
exit 1
|
||||
fi
|
||||
source ${CONFIG_DIR}/${2}/${2}.env
|
||||
SQLIMAGE=$(grep -iEo 'postgres\:.+' ${CONFIG_DIR}/${2}/docker-compose.yml|head -n1)
|
||||
docker run --rm \
|
||||
--network $(docker network ls -qf name=${2}_internal) \
|
||||
-v ${RUNTIME_DIR}/${2}/postgres:/var/lib/postgresql/data \
|
||||
--entrypoint= \
|
||||
-v ${DATA_DIR}/${2}/dumps:/dump \
|
||||
${SQLIMAGE} /bin/sh -c "pg_dump -Fc postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-${2}} -f /dump/postgres-$(date +${DATEFORMAT}).dump; \
|
||||
ls -tp /dump/postgres*| grep -v '/$' | tail -n +${DB_KEEPLATEST:-4} | xargs -d '\n' -r rm --"
|
||||
check $?
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function runBorgBackup() {
|
||||
if [[ ! ${1} =~ (${SERVICE}|${DUMPSERVICE}) ]]; then
|
||||
echo "First parameter needs specify the service: '${SERVICE}'"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f ${TMPDIR}/fileList.borg ]]; then
|
||||
echo 'No file list for borg is present in tmpdir!'
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f ${TMPDIR}/excludeList.borg ]]; then
|
||||
touch ${TMPDIR}/excludeList.borg
|
||||
fi
|
||||
|
||||
for ((i=1;i<=${#BORG_REPOS[@]};i++))
|
||||
do
|
||||
BORG_REPO=${BORG_REPOS[$i]}
|
||||
export BORG_PASSPHRASE=${BORG_PASSPHRASES[$i]}
|
||||
echo "Push backup of ${1} to $BORG_REPO..."
|
||||
borg create -v --stats --compression lz4 --exclude-from ${TMPDIR}/excludeList.borg \
|
||||
${BORG_REPO}::${1}'-{now:%Y-%m-%d_%H:%M:%S}' $(<${TMPDIR}/fileList.borg)
|
||||
check $?
|
||||
echo
|
||||
done
|
||||
>${TMPDIR}/excludeList.borg
|
||||
>${TMPDIR}/fileList.borg
|
||||
}
|
||||
|
||||
function runBorgPrune() {
|
||||
if [[ ! ${1} =~ (${SERVICE}|${DUMPSERVICE}) ]]; then
|
||||
echo "First parameter needs specify the service: '${SERVICE}'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
echo "###### Pruning backup for ${1} on $(date) ######"
|
||||
for ((i=1;i<=${#BORG_REPOS[@]};i++))
|
||||
do
|
||||
BORG_REPO=${BORG_REPOS[$i]}
|
||||
export BORG_PASSPHRASE=${BORG_PASSPHRASES[$i]}
|
||||
borg prune -v --list --prefix ${1} ${BORG_REPO} \
|
||||
--keep-within=${BORG_KEEPWITHIN:-2d} \
|
||||
--keep-daily=${BORG_KEEPDAILY:-7} \
|
||||
--keep-weekly=${BORG_KEEPWEEKLY:-4} \
|
||||
--keep-monthly=${BORG_KEEPMONTHLY:-6}
|
||||
check $?
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
function pruneLogs() {
|
||||
cd ${LOGPATH}
|
||||
for ACT in ${ACTIONS[@]}
|
||||
do
|
||||
find . -maxdepth 1 -name "${ACT}*.log" | tail -n +${LOGS_KEEPLATEST:-6} | xargs -i rm -- {}
|
||||
done
|
||||
}
|
||||
|
||||
function showBorgStats() {
|
||||
for ((i=1;i<=${#BORG_REPOS[@]};i++))
|
||||
do
|
||||
BORG_REPO=${BORG_REPOS[$i]}
|
||||
export BORG_PASSPHRASE=${BORG_PASSPHRASES[$i]}
|
||||
#borg info ${1} ${BORG_REPO}
|
||||
echo
|
||||
done
|
||||
}
|
||||
|
||||
function mailcowBaR () {
|
||||
if [[ ! ${1} =~ (${MCSERVICE}|all) ]]; then
|
||||
echo "First parameter needs to be ${MCSERVICE}|all"
|
||||
exit 1
|
||||
fi
|
||||
echo "Execute mailcow backup script for ${1}..."
|
||||
MAILCOW_BACKUP_LOCATION=${ROOT_DIR}/data/mailcow/dumps /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup ${1} >/dev/null
|
||||
check $?
|
||||
cd ${ROOT_DIR}/data/mailcow/dumps/; ls -1 -d "$PWD/"* -t | tail -n +${DB_KEEPLATEST:-4} | xargs -i rm -r -- {}
|
||||
}
|
||||
|
||||
function nextcloudMaintenanceMode() {
|
||||
/usr/bin/docker exec $(docker ps -qf name=nextcloud_cron) php /var/www/html/occ maintenance:mode --${1:-off}
|
||||
}
|
||||
|
||||
function notifyAdmin() {
|
||||
if [ -f ${TMPDIR}/errorsOccured ]; then
|
||||
/usr/bin/mailx -a "From: ${HOST}.${DOMAIN} <root@${HOST}.${DOMAIN}>" -s "[${HOST}] ${ACTION} - errors occured" hostmaster@${DOMAIN} < ${LOGFILE}
|
||||
rm ${TMPDIR}/errorsOccured
|
||||
fi
|
||||
}
|
||||
|
||||
function check() {
|
||||
if [ $1 -eq 1 ]; then
|
||||
echo '==> FAILED!'
|
||||
if [ ! -f ${TMPDIR}/errorsOccured ]; then
|
||||
touch ${TMPDIR}/errorsOccured
|
||||
fi
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function dump() {
|
||||
while (( "$#" )); do
|
||||
case "${1}" in
|
||||
# nextcloud|all)
|
||||
# nextcloudMaintenanceMode on
|
||||
# dumpDBfromDocker postgres nextcloud
|
||||
# nextcloudMaintenanceMode off
|
||||
# ;;&
|
||||
wallabag|all)
|
||||
dumpDBfromDocker postgres wallabag
|
||||
;;&
|
||||
# ttrss|all)
|
||||
# dumpDBfromDocker postgres ttrss
|
||||
# ;;&
|
||||
ejabberd|all)
|
||||
dumpDBfromDocker postgres ejabberd
|
||||
;;&
|
||||
mailcow|all)
|
||||
while (( "$#" )); do
|
||||
case "${2}" in
|
||||
all)
|
||||
mailcowBaR all
|
||||
;;&
|
||||
vmail)
|
||||
mailcowBaR vmail
|
||||
;;&
|
||||
crypt)
|
||||
mailcowBaR crypt
|
||||
;;&
|
||||
redis)
|
||||
mailcowBaR redis
|
||||
;;&
|
||||
rspamd)
|
||||
mailcowBaR rspamd
|
||||
;;&
|
||||
postfix)
|
||||
mailcowBaR postfix
|
||||
;;&
|
||||
mysql)
|
||||
mailcowBaR mysql
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
function backup() {
|
||||
echo "###### Start backup of $HOST on $(date) ######"
|
||||
|
||||
while (( "$#" )); do
|
||||
case "${2}" in
|
||||
rootfs|all)
|
||||
echo 'Get current locally installed software...'
|
||||
dpkg --get-selections > ${BKPPATH}/software.list
|
||||
check $?
|
||||
cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
/root
|
||||
/home
|
||||
/opt
|
||||
EOT
|
||||
cat <<EOT >>${TMPDIR}/excludeList.borg
|
||||
/root/.ssh/rsyncnet*
|
||||
${LOGPATH}/*.log
|
||||
${RUNTIME_DIR}
|
||||
/opt/mailcow-dockerized
|
||||
${DATA_DIR}/nextcloud*
|
||||
${DATA_DIR}/wallabag*
|
||||
${DATA_DIR}/ttrss*
|
||||
${DATA_DIR}/mailcow*
|
||||
${DATA_DIR}/ejabberd*
|
||||
${DATA_DIR}/filer*
|
||||
EOT
|
||||
runBorgBackup rootfs
|
||||
;;&
|
||||
etc|rootfs)
|
||||
cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
/etc
|
||||
EOT
|
||||
cat <<EOT >>${TMPDIR}/excludeList.borg
|
||||
/etc/shadow*
|
||||
EOT
|
||||
runBorgBackup etc
|
||||
;;&
|
||||
# nextcloud|all)
|
||||
# dump nextcloud
|
||||
# nextcloudMaintenanceMode on
|
||||
# cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
# ${CONFIG_DIR}/nextcloud
|
||||
# ${DATA_DIR}/nextcloud
|
||||
#EOT
|
||||
# runBorgBackup nextcloud
|
||||
# nextcloudMaintenanceMode off
|
||||
# ;;&
|
||||
wallabag|all)
|
||||
dump wallabag
|
||||
cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
${CONFIG_DIR}/wallabag
|
||||
${DATA_DIR}/wallabag
|
||||
EOT
|
||||
runBorgBackup wallabag
|
||||
;;&
|
||||
# ttrss|all)
|
||||
# dump ttrss
|
||||
# cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
# ${CONFIG_DIR}/ttrss
|
||||
# ${DATA_DIR}/ttrss
|
||||
#EOT
|
||||
# runBorgBackup ttrss
|
||||
# ;;&
|
||||
ejabberd|all)
|
||||
dump ejabberd
|
||||
cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
${CONFIG_DIR}/ejabberd
|
||||
${DATA_DIR}/ejabberd
|
||||
${CONFIG_DIR}/filer
|
||||
${DATA_DIR}/filer
|
||||
EOT
|
||||
runBorgBackup ejabberd
|
||||
;;&
|
||||
mailcow|all)
|
||||
# if [ "${2}" -eq 'all' ] ; then
|
||||
# 3='all'
|
||||
# fi
|
||||
# while (( "$#" )); do
|
||||
# case "${3}" in
|
||||
# all)
|
||||
dump mailcow all
|
||||
cat <<EOT >>${TMPDIR}/fileList.borg
|
||||
${ROOT_DIR}/mailcow-dockerized
|
||||
${DATA_DIR}/mailcow
|
||||
EOT
|
||||
runBorgBackup mailcow
|
||||
# ;;
|
||||
# vmail)
|
||||
# dump mailcow vmail
|
||||
# # IMPLEMENT BACKUP VIA MC-VMAIL and so on!!
|
||||
# ;;
|
||||
# crypt)
|
||||
# dump mailcow crypt
|
||||
# ;;
|
||||
# redis)
|
||||
# dump mailcow redis
|
||||
# ;;
|
||||
# rspamd)
|
||||
# dump mailcow rspamd
|
||||
# ;;
|
||||
# postfix)
|
||||
# dump mailcow postfix
|
||||
# ;;
|
||||
# mysql)
|
||||
# dump mailcow mysql
|
||||
# ;;
|
||||
# esac
|
||||
# shift
|
||||
# done
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
function prune() {
|
||||
while (( "$#" )); do
|
||||
case "${2}" in
|
||||
rootfs|all)
|
||||
runBorgPrune rootfs
|
||||
;;&
|
||||
etc|all)
|
||||
runBorgPrune rootfs
|
||||
;;&
|
||||
# nextcloud|all)
|
||||
# runBorgPrune nextcloud
|
||||
# ;;&
|
||||
wallabag|all)
|
||||
runBorgPrune wallabag
|
||||
;;&
|
||||
# ttrss|all)
|
||||
# runBorgPrune ttrss
|
||||
# ;;&
|
||||
ejabberd|all)
|
||||
runBorgPrune ejabberd
|
||||
;;&
|
||||
mailcow|all)
|
||||
# if [ "${2}" = 'all' ] ; then
|
||||
# mailcowOpt='all'
|
||||
# fi
|
||||
# while (( "$#" )); do
|
||||
# case "${mailcowOpt}" in
|
||||
# all)
|
||||
runBorgPrune mailcow
|
||||
# ;;
|
||||
# vmail)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# crypt)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# redis)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# rspamd)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# postfix)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# mysql)
|
||||
# runBorgPrune mailcow
|
||||
# ;;
|
||||
# esac
|
||||
# shift
|
||||
# done
|
||||
# ;;&
|
||||
# all)
|
||||
# pruneLogs
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
}
|
||||
|
||||
# Write output to logfile
|
||||
exec > >(tee -i ${LOGFILE})
|
||||
exec 2>&1
|
||||
|
||||
if [[ ${ACTION} == 'dump' ]]; then
|
||||
dump ${@,,}
|
||||
elif [[ ${ACTION} == 'backup' ]]; then
|
||||
backup ${@,,}
|
||||
elif [[ ${ACTION} == 'restore' ]]; then
|
||||
echo 'Restore not yet implemented!'
|
||||
elif [[ ${ACTION} == 'prune' ]]; then
|
||||
prune ${@,,}
|
||||
elif [[ ${ACTION} == 'status' ]]; then
|
||||
showBorgStats ${2}
|
||||
fi
|
||||
echo "Finished!"
|
||||
notifyAdmin
|
||||
rm -r $TMPDIR
|
Loading…
Reference in a new issue