2021-11-30 18:20:42 +08:00
#!/bin/bash
# Functions
get_start_time( ) {
START_TIME = $( date +%s)
CURRENT_DATE = $( date --date @" $START_TIME " +"%Y%m%d_%H%M%S" )
}
get_expiration_time( ) {
END_TIME = $( date +%s)
END_DATE_READABLE = $( date --date @" $END_TIME " +"%d.%m.%Y - %H:%M:%S" )
DURATION = $(( END_TIME-START_TIME))
DURATION_SEC = $(( DURATION % 60 ))
DURATION_MIN = $(( ( DURATION / 60 ) % 60 ))
DURATION_HOUR = $(( DURATION / 3600 ))
DURATION_READABLE = $( printf "%02d hours %02d minutes %02d seconds" $DURATION_HOUR $DURATION_MIN $DURATION_SEC )
}
# Test if all volumes aren't empty
VOLUME_DIRS = " $( find /nextcloud_aio_volumes -mindepth 1 -maxdepth 1 -type d) "
mapfile -t VOLUME_DIRS <<< " $VOLUME_DIRS "
for directory in " ${ VOLUME_DIRS [@] } " ; do
if ! mountpoint -q " $directory " ; then
echo " $directory is not a mountpoint which is not allowed. "
exit 1
fi
done
# Check if target is mountpoint
if ! mountpoint -q /mnt/borgbackup; then
echo "/mnt/borgbackup is not a mountpoint which is not allowed"
exit 1
fi
# Check if target is empty
2022-03-23 06:18:46 +08:00
if [ " $BORG_MODE " != backup ] && [ " $BORG_MODE " != test ] && ! [ -f " $BORG_BACKUP_DIRECTORY /config " ] ; then
2021-11-30 18:20:42 +08:00
echo "The repository is empty. cannot perform check or restore."
exit 1
fi
2022-06-07 07:06:47 +08:00
# Do not continue if this file exists (needed for simple external blocking)
if [ -f " $BORG_BACKUP_DIRECTORY /aio-lockfile " ] ; then
echo "Not continuing because aio-lockfile exists - it seems like a script is externally running which is locking the backup archive."
echo "If this should not be the case, you can fix this by deleting the 'aio-lockfile' file from the backup archive directory."
exit 1
fi
2021-11-30 18:20:42 +08:00
# Create lockfile
if [ " $BORG_MODE " = backup ] || [ " $BORG_MODE " = restore ] ; then
touch "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
fi
# Do the backup
if [ " $BORG_MODE " = backup ] ; then
# Test if important files are present
if ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json" ] ; then
echo "configuration.json not present. Cannot perform the backup!"
exit 1
elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/config/config.php" ] ; then
echo "config.php is missing cannot perform backup"
exit 1
elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/database-dump.sql" ] ; then
echo "database-dump is missing. cannot perform backup"
exit 1
fi
# Test that nothing is empty
for directory in " ${ VOLUME_DIRS [@] } " ; do
if [ -z " $( ls -A " $directory " ) " ] ; then
echo " $directory is empty which is not allowed. "
exit 1
fi
done
2021-12-08 01:45:52 +08:00
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/export.failed" ] ; then
echo "Database export failed the last time. Most likely was the export time not high enough."
echo "Cannot create a backup now."
echo "Please report this to https://github.com/nextcloud/all-in-one/issues. Thanks!"
exit 1
fi
2021-11-30 18:20:42 +08:00
# Create backup folder
mkdir -p " $BORG_BACKUP_DIRECTORY "
# Initialize the repository if the target is empty
if ! [ -f " $BORG_BACKUP_DIRECTORY /config " ] ; then
# Don't initialize if already initialized
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ] ; then
echo "Cannot initialize a new repository as that was already done at least one time."
2022-09-03 21:43:40 +08:00
echo "If you still want to do so, you may delete the 'borg.config' file that is stored in the mastercontainer volume manually, which will allow you to initialize a new borg repository in the chosen directory."
2021-11-30 18:20:42 +08:00
exit 1
fi
echo "initializing repository..."
2022-09-03 21:43:40 +08:00
NEW_REPOSITORY = 1
2021-11-30 18:20:42 +08:00
if ! borg init --debug --encryption= repokey-blake2 " $BORG_BACKUP_DIRECTORY " ; then
echo "Could not initialize borg repository."
rm -f " $BORG_BACKUP_DIRECTORY /config "
exit 1
fi
borg config " $BORG_BACKUP_DIRECTORY " additional_free_space 2G
# Fix too large Borg cache
# https://borgbackup.readthedocs.io/en/stable/faq.html#the-borg-cache-eats-way-too-much-disk-space-what-can-i-do
BORG_ID = " $( borg config " $BORG_BACKUP_DIRECTORY " id) "
rm -r " /root/.cache/borg/ $BORG_ID /chunks.archive.d "
touch " /root/.cache/borg/ $BORG_ID /chunks.archive.d "
# Make a backup from the borg config file
if ! [ -f " $BORG_BACKUP_DIRECTORY /config " ] ; then
echo "The borg config file wasn't created. Something is wrong."
exit 1
fi
rm -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
if ! cp " $BORG_BACKUP_DIRECTORY /config " "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ; then
echo "Could not copy config file to second place. Cannot perform backup."
exit 1
fi
echo "Repository successfully initialized."
fi
# Perform backup
echo "Performing backup..."
# Borg options
# auto,zstd compression seems to has the best ratio based on:
# https://forum.level1techs.com/t/optimal-compression-for-borg-backups/145870/6
2022-08-31 20:22:11 +08:00
BORG_OPTS = ( --stats --compression "auto,zstd" --exclude-caches --checkpoint-interval 86400)
2021-11-30 18:20:42 +08:00
# Create the backup
echo "Starting the backup..."
get_start_time
if ! borg create " ${ BORG_OPTS [@] } " " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -nextcloud-aio " "/nextcloud_aio_volumes/" ; then
echo "Deleting the failed backup archive..."
2022-08-31 20:22:11 +08:00
borg delete --stats " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -nextcloud-aio "
2021-11-30 18:20:42 +08:00
echo "Backup failed!"
2022-09-03 21:43:40 +08:00
if [ " $NEW_REPOSITORY " = 1 ] ; then
echo "Deleting borg.config file so that you can choose a different location for the backup."
rm "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
fi
2021-11-30 18:20:42 +08:00
exit 1
fi
2021-12-08 01:45:52 +08:00
# Remove the update skip file because the backup was successful
rm -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
2021-11-30 18:20:42 +08:00
# Prune options
2022-08-31 20:22:11 +08:00
BORG_PRUNE_OPTS = ( --stats --keep-within= 7d --keep-weekly= 4 --keep-monthly= 6 " $BORG_BACKUP_DIRECTORY " )
2021-11-30 18:20:42 +08:00
# Prune archives
echo "Pruning the archives..."
if ! borg prune --prefix '*_*-nextcloud-aio' " ${ BORG_PRUNE_OPTS [@] } " ; then
echo "Failed to prune archives!"
exit 1
fi
2022-10-25 01:46:09 +08:00
# Compact archives
echo "Compacting the archives..."
if ! borg compact " $BORG_BACKUP_DIRECTORY " ; then
echo "Failed to compact archives!"
exit 1
fi
2022-08-22 23:35:03 +08:00
# Back up additional directories of the host
if [ " $ADDITIONAL_DIRECTORIES_BACKUP " = 'yes' ] ; then
if [ -d "/docker_volumes/" ] ; then
DOCKER_VOLUME_DIRS = " $( find /docker_volumes -mindepth 1 -maxdepth 1 -type d) "
mapfile -t DOCKER_VOLUME_DIRS <<< " $DOCKER_VOLUME_DIRS "
for directory in " ${ DOCKER_VOLUME_DIRS [@] } " ; do
if [ -z " $( ls -A " $directory " ) " ] ; then
echo " $directory is empty which is not allowed. "
exit 1
fi
done
if ! borg create " ${ BORG_OPTS [@] } " " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -additional-docker-volumes " "/docker_volumes/" ; then
echo "Deleting the failed backup archive..."
2022-08-31 20:22:11 +08:00
borg delete --stats " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -additional-docker-volumes "
2022-08-22 23:35:03 +08:00
echo "Backup of additional docker-volumes failed!"
exit 1
fi
if ! borg prune --prefix '*_*-additional-docker-volumes' " ${ BORG_PRUNE_OPTS [@] } " ; then
echo "Failed to prune additional docker-volumes archives!"
exit 1
fi
2022-10-25 01:46:09 +08:00
if ! borg compact " $BORG_BACKUP_DIRECTORY " ; then
echo "Failed to compact archives!"
exit 1
fi
2022-08-22 23:35:03 +08:00
fi
if [ -d "/host_mounts/" ] ; then
EXCLUDED_DIRECTORIES = ( home/*/.cache root/.cache var/cache lost+found run var/run dev tmp sys proc)
# Exclude borg backup cache
EXCLUDED_DIRECTORIES += ( var/lib/docker/volumes/nextcloud_aio_backup_cache/_data)
# Exclude target directory
if [ -n " $BORGBACKUP_HOST_LOCATION " ] && [ " $BORGBACKUP_HOST_LOCATION " != "nextcloud_aio_backupdir" ] ; then
EXCLUDED_DIRECTORIES += ( " $BORGBACKUP_HOST_LOCATION " )
fi
for directory in " ${ EXCLUDED_DIRECTORIES [@] } "
do
EXCLUDE_DIRS += ( --exclude " /host_mounts/ $directory / " )
done
2022-08-26 01:03:29 +08:00
if ! borg create " ${ BORG_OPTS [@] } " " ${ EXCLUDE_DIRS [@] } " " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -additional-host-mounts " "/host_mounts/" ; then
2022-08-22 23:35:03 +08:00
echo "Deleting the failed backup archive..."
2022-08-31 20:22:11 +08:00
borg delete --stats " $BORG_BACKUP_DIRECTORY :: $CURRENT_DATE -additional-host-mounts "
2022-08-22 23:35:03 +08:00
echo "Backup of additional host-mounts failed!"
exit 1
fi
if ! borg prune --prefix '*_*-additional-host-mounts' " ${ BORG_PRUNE_OPTS [@] } " ; then
echo "Failed to prune additional host-mount archives!"
exit 1
fi
2022-10-25 01:46:09 +08:00
if ! borg compact " $BORG_BACKUP_DIRECTORY " ; then
echo "Failed to compact archives!"
exit 1
fi
2022-08-22 23:35:03 +08:00
fi
fi
2021-11-30 18:20:42 +08:00
# Inform user
get_expiration_time
echo " Backup finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ) "
2022-08-15 20:00:48 +08:00
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/update.failed" ] ; then
echo "However a Nextcloud update failed. So reporting that the backup failed which will skip any update attempt the next time."
echo "Please restore a backup from before the failed Nextcloud update attempt."
exit 1
fi
2021-11-30 18:20:42 +08:00
exit 0
fi
# Do the restore
if [ " $BORG_MODE " = restore ] ; then
get_start_time
# Perform the restore
2021-12-08 02:10:05 +08:00
if [ -n " $SELECTED_RESTORE_TIME " ] ; then
2022-02-16 22:05:04 +08:00
SELECTED_ARCHIVE = " $( borg list " $BORG_BACKUP_DIRECTORY " | grep "nextcloud-aio" | grep " $SELECTED_RESTORE_TIME " | awk -F " " '{print $1}' | head -1) "
2021-12-08 02:10:05 +08:00
else
SELECTED_ARCHIVE = " $( borg list " $BORG_BACKUP_DIRECTORY " | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1) "
fi
echo " Restoring ' $SELECTED_ARCHIVE '... "
2021-11-30 18:20:42 +08:00
mkdir -p /tmp/borg
2021-12-08 02:10:05 +08:00
if ! borg mount " $BORG_BACKUP_DIRECTORY :: $SELECTED_ARCHIVE " /tmp/borg; then
2021-11-30 18:20:42 +08:00
echo "Could not mount the backup!"
exit 1
fi
2022-03-21 20:23:17 +08:00
2022-08-26 21:04:52 +08:00
# Save Additional Backup dirs
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/additional_backup_directories" ] ; then
ADDITIONAL_BACKUP_DIRECTORIES = " $( cat /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/additional_backup_directories) "
fi
2022-08-26 21:26:51 +08:00
# Save daily backup time
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time" ] ; then
DAILY_BACKUPTIME = " $( cat /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time) "
fi
2022-03-30 22:35:04 +08:00
# Restore everything except the configuration file
2021-12-08 00:49:00 +08:00
if ! rsync --stats --archive --human-readable -vv --delete \
2021-12-30 02:57:26 +08:00
--exclude "nextcloud_aio_mastercontainer/session/" ** \
--exclude "nextcloud_aio_mastercontainer/certs/" ** \
2022-04-05 01:12:07 +08:00
--exclude "nextcloud_aio_mastercontainer/data/daily_backup_running" \
2022-10-16 23:37:13 +08:00
--exclude "nextcloud_aio_mastercontainer/data/session_date_file" \
2022-03-30 22:35:04 +08:00
--exclude "nextcloud_aio_mastercontainer/data/configuration.json" \
2022-11-22 02:03:17 +08:00
--exclude "nextcloud_aio_apache/caddy/" ** \
--exclude "nextcloud_aio_mastercontainer/caddy/" ** \
2021-12-08 00:49:00 +08:00
/tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes; then
2022-03-30 22:35:04 +08:00
echo "Something failed while restoring from backup."
2021-11-30 18:20:42 +08:00
umount /tmp/borg
exit 1
fi
2022-03-30 22:35:04 +08:00
# Save current aio password
AIO_PASSWORD = " $( jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
# Save current path
BORG_LOCATION = " $( jq '.borg_backup_host_location' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
2022-04-04 02:46:28 +08:00
# Save current nextcloud datadir
if grep -q '"nextcloud_datadir":' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
NEXTCLOUD_DATADIR = " $( jq '.nextcloud_datadir' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
else
NEXTCLOUD_DATADIR = '""'
fi
2022-03-30 22:35:04 +08:00
# Restore the configuration file
if ! rsync --archive --human-readable -vv \
/tmp/borg/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json \
/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json; then
echo "Something failed while restoring the configuration.json."
umount /tmp/borg
exit 1
fi
# Set backup-mode to restore since it was a restore
CONTENTS = " $( jq '."backup-mode" = "restore"' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
echo -E " ${ CONTENTS } " > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
# Reset the backup path to the currently used one
CONTENTS = " $( jq " .borg_backup_host_location = $BORG_LOCATION " /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
echo -E " ${ CONTENTS } " > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
# Reset the AIO password to the currently used one
CONTENTS = " $( jq " .password = $AIO_PASSWORD " /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
echo -E " ${ CONTENTS } " > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
2022-04-04 02:46:28 +08:00
# Reset the datadir to the one that was used for the restore
CONTENTS = " $( jq " .nextcloud_datadir = $NEXTCLOUD_DATADIR " /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
echo -E " ${ CONTENTS } " > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
2022-08-22 23:35:03 +08:00
# Reset the additional backup directories
if [ -n " $ADDITIONAL_BACKUP_DIRECTORIES " ] ; then
echo " $ADDITIONAL_BACKUP_DIRECTORIES " > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/additional_backup_directories"
chown 33:0 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/additional_backup_directories"
chmod 770 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/additional_backup_directories"
fi
2022-08-26 21:26:51 +08:00
# Reset the additional backup directories
if [ -n " $DAILY_BACKUPTIME " ] ; then
echo " $DAILY_BACKUPTIME " > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time"
chown 33:0 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time"
chmod 770 "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_time"
fi
2021-11-30 18:20:42 +08:00
umount /tmp/borg
# Inform user
get_expiration_time
echo " Restore finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ) "
2021-12-08 01:45:52 +08:00
# Add file to Nextcloud container so that it skips any update the next time
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
2022-04-26 21:44:13 +08:00
# Add file to Nextcloud container so that it performs a fingerprint update the next time
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/fingerprint.update"
2021-11-30 18:20:42 +08:00
fi
# Do the Backup check
if [ " $BORG_MODE " = check ] ; then
get_start_time
2022-03-11 16:27:38 +08:00
echo "Checking the backup integrity..."
2021-11-30 18:20:42 +08:00
# Perform the check
2022-08-31 20:22:11 +08:00
if ! borg check --verify-data " $BORG_BACKUP_DIRECTORY " ; then
2021-11-30 18:20:42 +08:00
echo "Some errors were found while checking the backup integrity!"
exit 1
fi
# Inform user
get_expiration_time
echo " Check finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ) "
exit 0
fi
2022-03-21 20:23:17 +08:00
# Do the backup test
if [ " $BORG_MODE " = test ] ; then
if ! [ -d " $BORG_BACKUP_DIRECTORY " ] ; then
echo "No 'borg' directory in the given backup directory found!"
2022-04-24 18:57:23 +08:00
echo "Only the files/folders below have been found in the given directory."
ls -a " $MOUNT_DIR "
2022-03-21 20:23:17 +08:00
echo "Please adjust the directory so that the borg archive is positioned in a folder named 'borg' inside the given directory!"
exit 1
elif ! [ -f " $BORG_BACKUP_DIRECTORY /config " ] ; then
echo "A 'borg' directory was found but could not find the borg archive."
2022-04-24 18:57:23 +08:00
echo "Only the files/folders below have been found in the borg directory."
ls -a " $BORG_BACKUP_DIRECTORY "
echo "The archive and most importantly the config file must be positioned directly in the 'borg' subfolder."
2022-03-21 20:23:17 +08:00
exit 1
elif ! borg list " $BORG_BACKUP_DIRECTORY " ; then
echo "The entered path seems to be valid but could not open the backup archive."
echo "Most likely the entered password was wrong so please adjust it accordingly!"
exit 1
else
echo "Everything looks fine so feel free to continue!"
exit 0
fi
fi