2021-11-30 11:20:42 +01: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
2023-05-17 20:48:08 +02:00
# Test if default volumes are there
DEFAULT_VOLUMES = ( nextcloud_aio_apache nextcloud_aio_nextcloud nextcloud_aio_database nextcloud_aio_database_dump nextcloud_aio_elasticsearch nextcloud_aio_nextcloud_data nextcloud_aio_mastercontainer)
for volume in " ${ DEFAULT_VOLUMES [@] } " ; do
if ! mountpoint -q " /nextcloud_aio_volumes/ $volume " ; then
echo " $volume is missing which is not intended. "
exit 1
fi
done
2021-11-30 11:20:42 +01:00
# Check if target is mountpoint
2024-11-07 22:19:56 +01:00
if [ -z " $BORG_REMOTE_REPO " ] && ! mountpoint -q " $MOUNT_DIR " ; then
echo " $MOUNT_DIR is not a mountpoint which is not allowed. "
2021-11-30 11:20:42 +01:00
exit 1
fi
2024-11-07 22:19:56 +01:00
# Check if repo is uninitialized
if [ " $BORG_MODE " != backup ] && [ " $BORG_MODE " != test ] && ! borg info > /dev/null; then
if [ -n " $BORG_REMOTE_REPO " ] ; then
echo "The repository is uninitialized or cannot connect to remote. Cannot perform check or restore."
else
echo "The repository is uninitialized. Cannot perform check or restore."
fi
2021-11-30 11:20:42 +01:00
exit 1
fi
2022-06-07 01:06:47 +02:00
# Do not continue if this file exists (needed for simple external blocking)
2024-11-07 22:19:56 +01:00
if [ -z " $BORG_REMOTE_REPO " ] && [ -f " $BORG_BACKUP_DIRECTORY /aio-lockfile " ] ; then
2023-08-28 08:43:01 +02:00
echo "Not continuing because aio-lockfile exists – it seems like a script is externally running which is locking the backup archive."
2022-06-07 01:06:47 +02:00
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 11:20:42 +01:00
# Create lockfile
if [ " $BORG_MODE " = backup ] || [ " $BORG_MODE " = restore ] ; then
touch "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
fi
2024-11-07 22:19:56 +01:00
if [ -n " $BORG_REMOTE_REPO " ] && ! [ -f " $BORGBACKUP_KEY " ] ; then
echo "First run, creating borg ssh key"
ssh-keygen -f " $BORGBACKUP_KEY " -N ""
echo "You should configure the remote to accept this public key"
fi
2024-11-08 14:50:35 +01:00
if [ -n " $BORG_REMOTE_REPO " ] && [ -f " $BORGBACKUP_KEY .pub " ] ; then
2024-11-08 14:29:36 +01:00
echo " Your public ssh key for borgbackup is: $( cat " $BORGBACKUP_KEY .pub " ) "
fi
2024-11-07 22:19:56 +01:00
2021-11-30 11:20:42 +01:00
# 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
2023-08-27 21:37:14 +02:00
echo "config.php is missing. Cannot perform backup!"
2021-11-30 11:20:42 +01:00
exit 1
elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/database-dump.sql" ] ; then
2023-08-27 21:37:14 +02:00
echo "database-dump is missing. Cannot perform backup!"
2024-01-09 13:17:24 +01:00
echo "Please check the database container logs!"
exit 1
2024-09-12 16:37:59 +02:00
elif ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.ocdata" ] && ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.ncdata" ] ; then
echo "The .ncdata or .ocdata file is missing in Nextcloud datadir which means it is invalid!"
2024-01-09 13:17:24 +01:00
echo "Is the drive where the datadir is located on still mounted?"
2021-11-30 11:20:42 +01:00
exit 1
fi
2023-10-30 10:57:59 +01:00
# Test that default volumes are not empty
for volume in " ${ DEFAULT_VOLUMES [@] } " ; do
if [ -z " $( ls -A " /nextcloud_aio_volumes/ $volume " ) " ] && [ " $volume " != "nextcloud_aio_elasticsearch" ] ; then
echo " /nextcloud_aio_volumes/ $volume is empty which should not happen! "
2021-11-30 11:20:42 +01:00
exit 1
fi
done
2021-12-07 18:45:52 +01:00
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/export.failed" ] ; then
echo "Cannot create a backup now."
2023-08-29 12:02:46 +02:00
echo "Reason is that the database export failed the last time."
echo "Most likely was the database container not correctly shut down via the AIO interface."
echo ""
echo "You might want to try the database export again manually by running the three commands:"
echo "sudo docker start nextcloud-aio-database"
echo "sleep 10"
echo "sudo docker stop nextcloud-aio-database -t 1800"
echo ""
echo "Afterwards try to create a backup again and it should hopefully work."
echo "If it should still fail, feel free to report this to https://github.com/nextcloud/all-in-one/issues and post the database container logs and the borgbackup container logs into the thread. Thanks!"
2021-12-07 18:45:52 +01:00
exit 1
fi
2024-11-07 22:19:56 +01:00
if [ -z " $BORG_REMOTE_REPO " ] ; then
# Create backup folder
mkdir -p " $BORG_BACKUP_DIRECTORY "
fi
2021-11-30 11:20:42 +01:00
2024-11-07 22:19:56 +01:00
# Initialize the repository if can't get info from target
if ! borg info > /dev/null; then
2021-11-30 11:20:42 +01:00
# Don't initialize if already initialized
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ] ; then
2024-11-07 22:19:56 +01:00
if [ -n " $BORG_REMOTE_REPO " ] ; then
echo "Borg could not get info from the remote repo."
echo "This might be a failure to connect to the remote server. See the above borg info output for details."
else
echo "Borg could not get info from the targeted directory."
echo "This might happen if the targeted directory is located on an external drive and the drive not connected anymore. You should check this."
fi
2023-05-09 00:54:15 +02:00
echo "If you instead want to initialize a new backup repository, 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:"
2023-01-17 18:22:37 +01:00
echo "sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/borg.config"
2021-11-30 11:20:42 +01:00
exit 1
fi
2023-08-27 21:37:14 +02:00
echo "Initializing repository..."
2022-09-03 15:43:40 +02:00
NEW_REPOSITORY = 1
2024-11-07 22:19:56 +01:00
if ! borg init --debug --encryption= repokey-blake2; then
2021-11-30 11:20:42 +01:00
echo "Could not initialize borg repository."
exit 1
fi
2024-11-07 22:19:56 +01:00
if [ -z " $BORG_REMOTE_REPO " ] ; then
# borg config only works for local repos; it's up to the remote to ensure the disk isn't full
borg config :: 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 :: id) "
rm -r " /root/.cache/borg/ $BORG_ID /chunks.archive.d "
touch " /root/.cache/borg/ $BORG_ID /chunks.archive.d "
fi
2021-11-30 11:20:42 +01:00
2024-11-07 22:19:56 +01:00
if ! borg info > /dev/null; then
echo "Borg can't get info from the repo it created. Something is wrong."
2021-11-30 11:20:42 +01:00
exit 1
fi
2024-11-07 22:19:56 +01:00
2021-11-30 11:20:42 +01:00
rm -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
2024-11-07 22:19:56 +01:00
if [ -n " $BORG_REMOTE_REPO " ] ; then
# `borg config` does not support remote repos so instead create a dummy file and rely on the remote to avoid
# corruption of the config file (which contains the encryption key). We don't actually use the contents of
# this file anywhere, so a touch is all we need so we remember we already initialized the repo.
touch "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config"
else
# Make a backup from the borg config file
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
2021-11-30 11:20:42 +01:00
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
2025-04-29 11:43:01 +02:00
BORG_OPTS = ( -v --stats --compression "auto,zstd" )
if [ " $NEW_REPOSITORY " = 1 ] ; then
BORG_OPTS += ( --progress)
fi
2021-11-30 11:20:42 +01:00
2023-03-02 16:39:18 +01:00
# Exclude the nextcloud log and audit log for GDPR reasons
2025-03-30 17:53:42 +02:00
BORG_EXCLUDE = ( --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log" --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/lost+found" )
2025-02-04 19:29:22 +01:00
BORG_INCLUDE = ( )
# Exclude datadir if .noaiobackup file was found
# shellcheck disable=SC2144
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ] ; then
BORG_EXCLUDE += ( --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/" )
BORG_INCLUDE += ( --pattern= "+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" )
2025-10-24 09:59:57 +02:00
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory from backup!"
2025-02-04 19:29:22 +01:00
# Exclude preview folder if .noaiobackup file was found
elif [ -f /nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup ] ; then
BORG_EXCLUDE += ( --exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/" )
BORG_INCLUDE += ( --pattern= "+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup" )
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in the preview directory. Excluding the preview directory from backup!"
fi
2023-03-02 16:39:18 +01:00
2023-05-09 00:54:15 +02:00
# Make sure that there is always a borg.config file before creating a new backup
if ! [ -f "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/borg.config" ] ; then
echo "Did not find borg.config file in the mastercontainer volume."
echo "Cannot create a backup as this is wrong."
exit 1
fi
2021-11-30 11:20:42 +01:00
# Create the backup
echo "Starting the backup..."
get_start_time
2025-02-04 19:29:22 +01:00
if ! borg create " ${ BORG_OPTS [@] } " " ${ BORG_INCLUDE [@] } " " ${ BORG_EXCLUDE [@] } " " :: $CURRENT_DATE -nextcloud-aio " "/nextcloud_aio_volumes/" --exclude-from /borg_excludes; then
2021-11-30 11:20:42 +01:00
echo "Deleting the failed backup archive..."
2024-11-07 22:19:56 +01:00
borg delete --stats " :: $CURRENT_DATE -nextcloud-aio "
2021-11-30 11:20:42 +01:00
echo "Backup failed!"
2023-04-18 13:22:10 +02:00
echo "You might want to check the backup integrity via the AIO interface."
2022-09-03 15:43:40 +02: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 11:20:42 +01:00
exit 1
fi
2021-12-07 18:45:52 +01: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 11:20:42 +01:00
# Prune options
2023-04-27 16:01:16 +02:00
read -ra BORG_PRUNE_OPTS <<< " $BORG_RETENTION_POLICY "
2023-05-30 16:25:24 +02:00
echo " BORG_PRUNE_OPTS are ${ BORG_PRUNE_OPTS [*] } "
2021-11-30 11:20:42 +01:00
# Prune archives
echo "Pruning the archives..."
2024-11-07 22:19:56 +01:00
if ! borg prune --stats --glob-archives '*_*-nextcloud-aio' " ${ BORG_PRUNE_OPTS [@] } " ; then
2021-11-30 11:20:42 +01:00
echo "Failed to prune archives!"
exit 1
fi
2022-10-24 19:46:09 +02:00
# Compact archives
echo "Compacting the archives..."
2024-11-07 22:19:56 +01:00
if ! borg compact; then
2022-10-24 19:46:09 +02:00
echo "Failed to compact archives!"
exit 1
fi
2022-08-22 17:35:03 +02: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
2022-12-29 10:06:50 +01:00
echo "Starting the backup for additional volumes..."
2024-11-07 22:19:56 +01:00
if ! borg create " ${ BORG_OPTS [@] } " " :: $CURRENT_DATE -additional-docker-volumes " "/docker_volumes/" ; then
2022-08-22 17:35:03 +02:00
echo "Deleting the failed backup archive..."
2024-11-07 22:19:56 +01:00
borg delete --stats " :: $CURRENT_DATE -additional-docker-volumes "
2022-08-22 17:35:03 +02:00
echo "Backup of additional docker-volumes failed!"
exit 1
fi
2022-12-29 10:06:50 +01:00
echo "Pruning additional volumes..."
2024-11-07 22:19:56 +01:00
if ! borg prune --stats --glob-archives '*_*-additional-docker-volumes' " ${ BORG_PRUNE_OPTS [@] } " ; then
2022-08-22 17:35:03 +02:00
echo "Failed to prune additional docker-volumes archives!"
exit 1
fi
2022-12-29 10:06:50 +01:00
echo "Compacting additional volumes..."
2024-11-07 22:19:56 +01:00
if ! borg compact; then
2023-08-27 21:37:14 +02:00
echo "Failed to compact additional docker-volume archives!"
2022-10-24 19:46:09 +02:00
exit 1
fi
2022-08-22 17:35:03 +02: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-12-29 10:06:50 +01:00
echo "Starting the backup for additional host mounts..."
2024-11-07 22:19:56 +01:00
if ! borg create " ${ BORG_OPTS [@] } " " ${ EXCLUDE_DIRS [@] } " " :: $CURRENT_DATE -additional-host-mounts " "/host_mounts/" ; then
2022-08-22 17:35:03 +02:00
echo "Deleting the failed backup archive..."
2024-11-07 22:19:56 +01:00
borg delete --stats " :: $CURRENT_DATE -additional-host-mounts "
2022-08-22 17:35:03 +02:00
echo "Backup of additional host-mounts failed!"
exit 1
fi
2022-12-29 10:06:50 +01:00
echo "Pruning additional host mounts..."
2024-11-07 22:19:56 +01:00
if ! borg prune --stats --glob-archives '*_*-additional-host-mounts' " ${ BORG_PRUNE_OPTS [@] } " ; then
2022-08-22 17:35:03 +02:00
echo "Failed to prune additional host-mount archives!"
exit 1
fi
2022-12-29 10:06:50 +01:00
echo "Compacting additional host mounts..."
2024-11-07 22:19:56 +01:00
if ! borg compact; then
2023-08-27 21:37:14 +02:00
echo "Failed to compact additional host-mount archives!"
2022-10-24 19:46:09 +02:00
exit 1
fi
2022-08-22 17:35:03 +02:00
fi
fi
2021-11-30 11:20:42 +01:00
# Inform user
get_expiration_time
2023-08-27 21:37:14 +02:00
echo " Backup finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ). "
2022-08-15 14:00:48 +02: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 11:20:42 +01:00
exit 0
fi
# Do the restore
if [ " $BORG_MODE " = restore ] ; then
get_start_time
2024-11-07 22:19:56 +01:00
# Pick archive to restore
2021-12-07 19:10:05 +01:00
if [ -n " $SELECTED_RESTORE_TIME " ] ; then
2024-11-07 22:19:56 +01:00
SELECTED_ARCHIVE = " $( borg list | grep "nextcloud-aio" | grep " $SELECTED_RESTORE_TIME " | awk -F " " '{print $1}' | head -1) "
2021-12-07 19:10:05 +01:00
else
2024-11-07 22:19:56 +01:00
SELECTED_ARCHIVE = " $( borg list | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1) "
2021-12-07 19:10:05 +01:00
fi
echo " Restoring ' $SELECTED_ARCHIVE '... "
2022-03-21 13:23:17 +01:00
2024-11-08 11:10:01 +01:00
ADDITIONAL_RSYNC_EXCLUDES = ( )
2024-11-11 14:48:08 +01:00
ADDITIONAL_BORG_EXCLUDES = ( )
ADDITIONAL_FIND_EXCLUDES = ( )
2025-02-04 19:29:22 +01:00
# Exclude datadir if .noaiobackup file was found
# shellcheck disable=SC2144
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ] ; then
# Keep these 3 in sync. Beware, the pattern syntax and the paths differ
ADDITIONAL_RSYNC_EXCLUDES = ( --exclude "nextcloud_aio_nextcloud_data/**" )
ADDITIONAL_BORG_EXCLUDES = ( --exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/**" )
ADDITIONAL_FIND_EXCLUDES = ( -o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data\(/.*\)?' )
2025-10-24 09:59:57 +02:00
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory from restore!"
2025-02-04 19:29:22 +01:00
echo "You might run into problems due to this afterwards as potentially this makes the directory go out of sync with the database."
echo "You might be able to fix this by running 'occ files:scan --all' and 'occ maintenance:repair' and 'occ files:scan-app-data' after the restore."
echo "See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands"
# Exclude previews from restore if selected to speed up process or exclude preview folder if .noaiobackup file was found
elif [ -n " $RESTORE_EXCLUDE_PREVIEWS " ] || [ -f /nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup ] ; then
2024-11-11 14:48:08 +01:00
# Keep these 3 in sync. Beware, the pattern syntax and the paths differ
2024-11-08 11:10:01 +01:00
ADDITIONAL_RSYNC_EXCLUDES = ( --exclude "nextcloud_aio_nextcloud_data/appdata_*/preview/**" )
2024-11-11 14:48:08 +01:00
ADDITIONAL_BORG_EXCLUDES = ( --exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/**" )
ADDITIONAL_FIND_EXCLUDES = ( -o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_[^/]*/preview\(/.*\)?' )
2025-02-04 19:29:22 +01:00
echo "⚠️⚠️⚠️ Excluding previews from restore!"
echo "You might run into problems due to this afterwards as potentially this makes the directory go out of sync with the database."
echo "You might be able to fix this by running 'occ files:scan-app-data preview' after the restore."
echo "See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands"
2024-11-08 11:10:01 +01:00
fi
2022-08-26 15:04:52 +02: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 15:26:51 +02: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 16:35:04 +02:00
# Save current aio password
AIO_PASSWORD = " $( jq '.password' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
2024-11-07 22:19:56 +01:00
# Save current backup location vars
2022-03-30 16:35:04 +02:00
BORG_LOCATION = " $( jq '.borg_backup_host_location' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
2024-11-07 22:19:56 +01:00
REMOTE_REPO = " $( jq '.borg_remote_repo' /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
2022-03-30 16:35:04 +02:00
2022-04-03 20:46:28 +02: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
2024-11-07 22:19:56 +01:00
if [ -z " $BORG_REMOTE_REPO " ] ; then
mkdir -p /tmp/borg
if ! borg mount " :: $SELECTED_ARCHIVE " /tmp/borg; then
echo "Could not mount the backup!"
exit 1
fi
# Restore everything except the configuration file
#
# These exclude patterns need to be kept in sync with the borg_excludes file and the find excludes in this file,
# which use a different syntax (patterns appear in 3 places in total)
if ! rsync --stats --archive --human-readable -vv --delete \
--exclude "nextcloud_aio_apache/caddy/**" \
--exclude "nextcloud_aio_mastercontainer/caddy/**" \
--exclude "nextcloud_aio_nextcloud/data/nextcloud.log*" \
--exclude "nextcloud_aio_nextcloud/data/audit.log" \
--exclude "nextcloud_aio_mastercontainer/certs/**" \
--exclude "nextcloud_aio_mastercontainer/data/configuration.json" \
--exclude "nextcloud_aio_mastercontainer/data/daily_backup_running" \
--exclude "nextcloud_aio_mastercontainer/data/session_date_file" \
--exclude "nextcloud_aio_mastercontainer/session/**" \
2025-03-30 17:53:42 +02:00
--exclude "nextcloud_aio_nextcloud_data/lost+found" \
2024-11-08 11:10:01 +01:00
" ${ ADDITIONAL_RSYNC_EXCLUDES [@] } " \
2024-11-07 22:19:56 +01:00
/tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes/; then
RESTORE_FAILED = 1
echo "Something failed while restoring from backup."
fi
# 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
RESTORE_FAILED = 1
echo "Something failed while restoring the configuration.json."
fi
if ! umount /tmp/borg; then
echo "Failed to unmount the borg archive but should still be able to restore successfully"
fi
else
# Restore nearly everything
#
# borg mount is really slow for remote repos (did not check whether it's slow for local repos too),
# using extract to /tmp would require temporarily storing a second copy of the data.
# So instead extract directly on top of the destination with exclude patterns for the config, but
# then we do still need to delete local files which are not present in the archive.
#
# Older backups may still contain files we've since excluded, so we have to exclude on extract as well.
cd / # borg extract has no destination arg and extracts to CWD
2024-11-11 14:48:08 +01:00
if ! borg extract " :: $SELECTED_ARCHIVE " --progress --exclude-from /borg_excludes " ${ ADDITIONAL_BORG_EXCLUDES [@] } " --pattern '+nextcloud_aio_volumes/**'
2024-11-07 22:19:56 +01:00
then
RESTORE_FAILED = 1
echo "Failed to extract backup archive."
else
# Delete files/dirs present locally, but not in the backup archive, excluding conf files
# https://unix.stackexchange.com/a/759341
# This comm does not support -z, but I doubt any file names would have \n in them
2024-11-11 14:48:08 +01:00
#
2024-11-07 22:19:56 +01:00
# These find patterns need to be kept in sync with the borg_excludes file and the rsync excludes in this
# file, which use a different syntax (patterns appear in 3 places in total)
2024-11-11 14:48:08 +01:00
echo "Deleting local files which do not exist in the backup"
2024-11-07 22:19:56 +01:00
if ! find nextcloud_aio_volumes \
-not \( \
-path nextcloud_aio_volumes/nextcloud_aio_apache/caddy \
-o -path "nextcloud_aio_volumes/nextcloud_aio_apache/caddy/*" \
-o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/caddy \
-o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/caddy/*" \
-o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/certs \
-o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/certs/*" \
-o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/session \
-o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/session/*" \
-o -path "nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/nextcloud.log*" \
-o -path nextcloud_aio_volumes/nextcloud_aio_nextcloud/data/audit.log \
-o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/daily_backup_running \
-o -path nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/session_date_file \
-o -path "nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/id_borg*" \
2025-03-30 17:53:42 +02:00
-o -path "nextcloud_aio_nextcloud_data/lost+found" \
2024-11-11 14:48:08 +01:00
" ${ ADDITIONAL_FIND_EXCLUDES [@] } " \
2024-11-07 22:19:56 +01:00
\) \
| LC_ALL = C sort \
| LC_ALL = C comm -23 - \
<( borg list " :: $SELECTED_ARCHIVE " --short --exclude-from /borg_excludes --pattern '+nextcloud_aio_volumes/**' | LC_ALL = C sort) \
> /tmp/local_files_not_in_backup
then
RESTORE_FAILED = 1
echo "Failed to delete local files not in backup archive."
else
# More robust than e.g. xargs as I got a ~"args line too long" error while testing that, but it's slower
# https://stackoverflow.com/a/21848934
while IFS = read -r file
do rm -vrf -- " $file " || DELETE_FAILED = 1
done < /tmp/local_files_not_in_backup
if [ " $DELETE_FAILED " = 1 ] ; then
RESTORE_FAILED = 1
echo "Failed to delete (some) local files not in backup archive."
fi
fi
fi
2022-03-30 16:35:04 +02:00
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
2024-11-07 22:19:56 +01:00
# Reset the backup location vars to the currently used one
2022-03-30 16:35:04 +02:00
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
2024-11-07 22:19:56 +01:00
CONTENTS = " $( jq " .borg_remote_repo = $REMOTE_REPO " /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json) "
echo -E " ${ CONTENTS } " > /nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/configuration.json
2022-03-30 16:35:04 +02:00
# 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-03 20:46:28 +02: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 17:35:03 +02: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 15:26:51 +02: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
2023-02-13 16:51:55 +01:00
if [ " $RESTORE_FAILED " = 1 ] ; then
exit 1
fi
2021-11-30 11:20:42 +01:00
# Inform user
get_expiration_time
2023-08-27 21:37:14 +02:00
echo " Restore finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ). "
2021-12-07 18:45:52 +01: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 15:44:13 +02: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"
2022-12-13 14:32:38 +01:00
2024-11-08 11:10:01 +01:00
# Add file to Netcloud container to trigger a preview scan the next time it starts
if [ -n " $RESTORE_EXCLUDE_PREVIEWS " ] ; then
touch "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/trigger-preview.scan"
chmod 777 "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/trigger-preview.scan"
fi
2022-12-13 14:32:38 +01:00
# Delete redis cache
rm -f "/mnt/redis/dump.rdb"
2021-11-30 11:20:42 +01:00
fi
# Do the Backup check
if [ " $BORG_MODE " = check ] ; then
get_start_time
2022-03-11 09:27:38 +01:00
echo "Checking the backup integrity..."
2021-11-30 11:20:42 +01:00
# Perform the check
2024-11-07 22:19:56 +01:00
if ! borg check -v --verify-data; then
2021-11-30 11:20:42 +01:00
echo "Some errors were found while checking the backup integrity!"
2025-01-22 11:04:52 +01:00
echo "Check the AIO interface for advice on how to proceed now!"
2021-11-30 11:20:42 +01:00
exit 1
fi
# Inform user
get_expiration_time
2023-08-27 21:37:14 +02:00
echo " Check finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ). "
2021-11-30 11:20:42 +01:00
exit 0
fi
2022-03-21 13:23:17 +01:00
2023-01-04 15:38:59 +01:00
# Do the Backup check-repair
if [ " $BORG_MODE " = "check-repair" ] ; then
get_start_time
echo "Checking the backup integrity and repairing it..."
# Perform the check-repair
2024-11-07 22:19:56 +01:00
if ! echo YES | borg check -v --repair; then
2023-01-04 15:38:59 +01:00
echo "Some errors were found while checking and repairing the backup integrity!"
exit 1
fi
# Inform user
get_expiration_time
2023-08-27 21:37:14 +02:00
echo " Check finished successfully on $END_DATE_READABLE ( $DURATION_READABLE ). "
2023-01-04 15:38:59 +01:00
exit 0
fi
2022-03-21 13:23:17 +01:00
# Do the backup test
if [ " $BORG_MODE " = test ] ; then
2024-11-07 22:19:56 +01:00
if [ -n " $BORG_REMOTE_REPO " ] ; then
if ! borg info > /dev/null; then
echo "Borg could not get info from the remote repo."
echo "See the above borg info output for details."
exit 1
fi
else
if ! [ -d " $BORG_BACKUP_DIRECTORY " ] ; then
echo "No 'borg' directory in the given backup directory found!"
echo "Only the files/folders below have been found in the given directory."
ls -a " $MOUNT_DIR "
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."
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."
exit 1
fi
fi
2024-11-13 18:53:38 +01:00
if ! borg list >/dev/null; then
2022-03-21 13:23:17 +01:00
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
2024-11-13 18:53:38 +01:00
if ! borg list | grep "nextcloud-aio" ; then
echo "The backup archive does not contain a valid Nextcloud AIO backup."
echo "Most likely was the archive not created via Nextcloud AIO."
exit 1
else
echo "Everything looks fine so feel free to continue!"
exit 0
fi
2022-03-21 13:23:17 +01:00
fi
fi