borgbackup: support .noaiobackup marker in arbitrary directories

Replace hardcoded .noaiobackup path checks with borg's native
--exclude-if-present option, allowing users to exclude any directory
from backup by placing a .noaiobackup marker file in it.

Changes:
- Backup: Use --exclude-if-present=.noaiobackup --keep-exclude-tags
- Restore: Dynamically detect .noaiobackup markers from backup archive
  (not local filesystem) and build exclude patterns accordingly
- Keep RESTORE_EXCLUDE_PREVIEWS as standalone feature
This commit is contained in:
JMoVS 2025-12-14 11:37:31 +01:00
parent 7c57a3f702
commit 26c93096e0

View file

@ -187,19 +187,17 @@ if [ "$BORG_MODE" = backup ]; then
# Exclude the nextcloud log and audit log for GDPR reasons # Exclude the nextcloud log and audit log for GDPR reasons
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") 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")
BORG_INCLUDE=()
# Exclude datadir if .noaiobackup file was found # Exclude any directory containing .noaiobackup marker (marker itself is kept in backup)
# shellcheck disable=SC2144 BORG_EXCLUDE+=(--exclude-if-present=.noaiobackup --keep-exclude-tags)
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ]; then
BORG_EXCLUDE+=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/") # Log which directories will be excluded due to .noaiobackup markers
BORG_INCLUDE+=(--pattern="+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup") NOAIOBACKUP_MARKERS=$(find /nextcloud_aio_volumes -name ".noaiobackup" -type f 2>/dev/null)
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory from backup!" if [ -n "$NOAIOBACKUP_MARKERS" ]; then
# Exclude preview folder if .noaiobackup file was found echo "The following directories will be excluded from backup due to .noaiobackup markers:"
elif [ -f /nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup ]; then echo "$NOAIOBACKUP_MARKERS" | while read -r marker; do
BORG_EXCLUDE+=(--exclude "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/") echo " - $(dirname "$marker")"
BORG_INCLUDE+=(--pattern="+/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/.noaiobackup") done
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in the preview directory. Excluding the preview directory from backup!"
fi fi
# Make sure that there is always a borg.config file before creating a new backup # Make sure that there is always a borg.config file before creating a new backup
@ -212,7 +210,7 @@ if [ "$BORG_MODE" = backup ]; then
# Create the backup # Create the backup
echo "Starting the backup..." echo "Starting the backup..."
get_start_time get_start_time
if ! borg create "${BORG_OPTS[@]}" "${BORG_INCLUDE[@]}" "${BORG_EXCLUDE[@]}" "::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/" --exclude-from /borg_excludes; then if ! borg create "${BORG_OPTS[@]}" "${BORG_EXCLUDE[@]}" "::$CURRENT_DATE-nextcloud-aio" "/nextcloud_aio_volumes/" --exclude-from /borg_excludes; then
echo "Deleting the failed backup archive..." echo "Deleting the failed backup archive..."
borg delete --stats "::$CURRENT_DATE-nextcloud-aio" borg delete --stats "::$CURRENT_DATE-nextcloud-aio"
echo "Backup failed!" echo "Backup failed!"
@ -329,27 +327,17 @@ if [ "$BORG_MODE" = restore ]; then
fi fi
echo "Restoring '$SELECTED_ARCHIVE'..." echo "Restoring '$SELECTED_ARCHIVE'..."
# Initialize exclude arrays - will be populated dynamically based on .noaiobackup markers in backup
ADDITIONAL_RSYNC_EXCLUDES=() ADDITIONAL_RSYNC_EXCLUDES=()
ADDITIONAL_BORG_EXCLUDES=() ADDITIONAL_BORG_EXCLUDES=()
ADDITIONAL_FIND_EXCLUDES=() ADDITIONAL_FIND_EXCLUDES=()
# Exclude datadir if .noaiobackup file was found
# shellcheck disable=SC2144 # Handle RESTORE_EXCLUDE_PREVIEWS env var (excludes previews even without .noaiobackup marker)
if [ -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/.noaiobackup" ]; then if [ -n "$RESTORE_EXCLUDE_PREVIEWS" ]; then
# Keep these 3 in sync. Beware, the pattern syntax and the paths differ ADDITIONAL_RSYNC_EXCLUDES+=(--exclude "nextcloud_aio_nextcloud_data/appdata_*/preview/**")
ADDITIONAL_RSYNC_EXCLUDES=(--exclude "nextcloud_aio_nextcloud_data/**") ADDITIONAL_BORG_EXCLUDES+=(--exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_*/preview/**")
ADDITIONAL_BORG_EXCLUDES=(--exclude "sh:nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/**") ADDITIONAL_FIND_EXCLUDES+=(-o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/appdata_[^/]*/preview\(/.*\)?')
ADDITIONAL_FIND_EXCLUDES=(-o -regex 'nextcloud_aio_volumes/nextcloud_aio_nextcloud_data\(/.*\)?') echo "RESTORE_EXCLUDE_PREVIEWS is set. Excluding previews from restore!"
echo "⚠️⚠️⚠️ '.noaiobackup' file was found in Nextcloud's data directory. Excluding the data directory 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 --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
# Keep these 3 in sync. Beware, the pattern syntax and the paths differ
ADDITIONAL_RSYNC_EXCLUDES=(--exclude "nextcloud_aio_nextcloud_data/appdata_*/preview/**")
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\(/.*\)?')
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 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 "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" echo "See https://github.com/nextcloud/all-in-one#how-to-run-occ-commands"
@ -386,10 +374,26 @@ if [ "$BORG_MODE" = restore ]; then
exit 1 exit 1
fi fi
# Restore everything except the configuration file # Find .noaiobackup markers in the BACKUP and build exclude list dynamically
# NOAIOBACKUP_FOUND=0
# These exclude patterns need to be kept in sync with the borg_excludes file and the find excludes in this file, while IFS= read -r marker; do
# which use a different syntax (patterns appear in 3 places in total) if [ -n "$marker" ]; then
NOAIOBACKUP_FOUND=1
# Get relative path from nextcloud_aio_volumes
rel_dir="${marker#/tmp/borg/nextcloud_aio_volumes/}"
rel_dir="$(dirname "$rel_dir")"
ADDITIONAL_RSYNC_EXCLUDES+=(--exclude "${rel_dir}/**")
echo "Excluding '$rel_dir' from restore due to .noaiobackup marker in backup"
fi
done < <(find /tmp/borg/nextcloud_aio_volumes -name ".noaiobackup" -type f 2>/dev/null)
if [ "$NOAIOBACKUP_FOUND" = 1 ]; then
echo "You might run into problems due to excluded directories 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"
fi
# Restore everything except the configuration file and excluded directories
if ! rsync --stats --archive --human-readable -vv --delete \ if ! rsync --stats --archive --human-readable -vv --delete \
--exclude "nextcloud_aio_apache/caddy/**" \ --exclude "nextcloud_aio_apache/caddy/**" \
--exclude "nextcloud_aio_mastercontainer/caddy/**" \ --exclude "nextcloud_aio_mastercontainer/caddy/**" \
@ -427,6 +431,27 @@ if [ "$BORG_MODE" = restore ]; then
# then we do still need to delete local files which are not present in the archive. # 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. # Older backups may still contain files we've since excluded, so we have to exclude on extract as well.
# Find .noaiobackup markers in the archive and build exclude lists dynamically
NOAIOBACKUP_FOUND=0
while IFS= read -r marker; do
if [ -n "$marker" ]; then
NOAIOBACKUP_FOUND=1
dir="$(dirname "$marker")"
ADDITIONAL_BORG_EXCLUDES+=(--exclude "sh:${dir}/**")
# Escape special regex chars and build pattern for recursive matching
escaped_dir=$(printf '%s' "$dir" | sed 's/[[\.*^$()+?{|]/\\&/g')
ADDITIONAL_FIND_EXCLUDES+=(-o -regex "${escaped_dir}\\(/.*\\)?")
echo "Excluding '$dir' from restore due to .noaiobackup marker in backup"
fi
done < <(borg list "::$SELECTED_ARCHIVE" --short | grep '\.noaiobackup$')
if [ "$NOAIOBACKUP_FOUND" = 1 ]; then
echo "You might run into problems due to excluded directories 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"
fi
cd / # borg extract has no destination arg and extracts to CWD cd / # borg extract has no destination arg and extracts to CWD
if ! borg extract "::$SELECTED_ARCHIVE" --progress --exclude-from /borg_excludes "${ADDITIONAL_BORG_EXCLUDES[@]}" --pattern '+nextcloud_aio_volumes/**' if ! borg extract "::$SELECTED_ARCHIVE" --progress --exclude-from /borg_excludes "${ADDITIONAL_BORG_EXCLUDES[@]}" --pattern '+nextcloud_aio_volumes/**'
then then