#!/bin/bash set -eE BACKUPFILE="$1" DBADMIN=ncadmin DBPASSWD="$( grep password /root/.my.cnf | sed 's|password=||' )" source /usr/local/etc/library.sh # sets PHPVER DIR="$( cd "$( dirname "$BACKUPFILE" )" &>/dev/null && pwd )" #abspath [[ -f /.docker-image ]] && NCDIR=/data/nextcloud || NCDIR=/var/www/nextcloud [[ $# -eq 0 ]] && { echo "missing first argument" ; exit 1; } [[ -f "$BACKUPFILE" ]] || { echo "$BACKUPFILE not found" ; exit 1; } [[ "$DIR" =~ "$NCDIR".* ]] && { echo "Refusing to restore from $NCDIR"; exit 1; } TEMPDIR="$( mktemp -d "$( dirname "$BACKUPFILE" )"/ncp-restore.XXXXXX )" || { echo "Failed to create temp dir" >&2; exit 1; } [[ "$(stat -fc%T "${TEMPDIR}")" =~ ext|btrfs|zfs ]] || { echo "Can only restore from ext/btrfs/zfs filesystems (found '$(stat -fc%T "${TEMPDIR}")" >&2; exit 1; } TEMPDIR="$( cd "$TEMPDIR" &>/dev/null && pwd )" || { echo "$TEMPDIR not found"; exit 1; } #abspath cleanup(){ local RET=$?; echo "Cleanup..."; rm -rf "${TEMPDIR}"; trap "" EXIT; exit $RET; } trap cleanup INT TERM HUP ERR EXIT rm -rf "$TEMPDIR" && mkdir -p "$TEMPDIR" [[ "$BACKUPFILE" =~ .*".tar.gz" ]] && compress_arg="-I pigz" # CHECK FREE SPACE IN $TEMPDIR echo "check free space..." # allow at least ~100 extra MiB extractedsize=$(tar $compress_arg -tvf "$BACKUPFILE" | awk '{s+=$3} END{printf "%.0f", (s/1024)}') # Size of extracted files in "KB" size=$(($extractedsize + 100*1024)) free=$( df "$TEMPDIR" | tail -1 | awk '{ print $4 }' ) [ $size -ge $free ] && { echo "free space check failed. Need $size KB in $TEMPDIR"; exit 1; } # EXTRACT FILES echo "extracting backup file $BACKUPFILE..." tar $compress_arg -xf "$BACKUPFILE" -C "$TEMPDIR" || exit 1 ## SANITY CHECKS [[ -d "$TEMPDIR"/nextcloud ]] && [[ -f "$( ls "$TEMPDIR"/nextcloud-sqlbkp_*.bak 2>/dev/null )" ]] || { echo "invalid backup file. Abort" exit 1 } ## RESTORE FILES echo "restore files..." [[ -d "$NCDIR/data" ]] && { DATA_BKP_DIR="$(mktemp -d -p "$NCDIR/.." nc-data-XXXXXX)" mv -T "$NCDIR/data" "$DATA_BKP_DIR/" } rm -rf "$NCDIR" mv -T "$TEMPDIR"/nextcloud "$NCDIR" || { echo "Error restoring base files"; exit 1; } if [[ -n "$DATA_BKP_DIR" ]] then target="$NCDIR/data" [[ -d "$target" ]] && { target="$NCDIR/.data_$(date '+%FT%s')" echo "DATA CONFLICT! Your old '$NCDIR/data' directory can be found in '$target' after the restore script is done. The new '$NCDIR/data' directory will be restored from the backup. You can manually merge these directories with this command (run nc-fix-permissions and nc-scan afterwards): cp -rn '$target/'* '$target/'.[!.]* '$NCDIR/data/'" } echo "Restoring old '$NCDIR/data' to '$target'..." mv -T "$DATA_BKP_DIR" "$target" fi # update NC database password to this instance sed -i "s|'dbpassword' =>.*|'dbpassword' => '$DBPASSWD',|" /var/www/nextcloud/config/config.php # update redis credentials REDISPASS="$( grep "^requirepass" /etc/redis/redis.conf | cut -f2 -d' ' )" [[ "$REDISPASS" != "" ]] && \ sed -i "s|'password'.*|'password' => '$REDISPASS',|" /var/www/nextcloud/config/config.php service redis-server restart ## RE-CREATE DATABASE TABLE echo "restore database..." mysql -u root </dev/null && { rmdir "$DATADIR" || exit 1 btrfs subvolume create "$DATADIR" || exit 1 } chown www-data: "$DATADIR" TMPDATA="$TEMPDIR/$( basename "$DATADIR" )" mv "$TMPDATA"/* "$TMPDATA"/.[!.]* "$DATADIR" || exit 1 rmdir "$TMPDATA" || exit 1 ncc maintenance:mode --off ### INCLUDEDATA=no situation else echo "No datadir found in backup" [[ -e "$DATADIR" ]] || { echo -n "${DATADIR} not found." DATADIR="/data/ncdata/data" is_docker || DATADIR="/opt/data" echo "Resetting to ${DATADIR}" mkdir -p "${DATADIR}" touch "${DATADIR}"/.ocdata chown -R www-data: "${DATADIR}" } ncc maintenance:mode --off ncc files:scan --all # cache needs to be cleaned as of NC 12 NEED_RESTART=1 fi sed -i "s|'datadirectory' =>.*|'datadirectory' => '${DATADIR}',|" "${NCDIR}"/config/config.php # Just in case we moved the opcache dir install_template "php/opcache.ini.sh" "/etc/php/${PHPVER}/mods-available/opcache.ini" # tmp upload dir mkdir -p "$DATADIR/tmp" chown www-data: "$DATADIR/tmp" ncc config:system:set tempdirectory --value "$DATADIR/tmp" sed -i "s|^;\?upload_tmp_dir =.*$|upload_tmp_dir = $DATADIR/tmp|" "/etc/php/${PHPVER}/cli/php.ini" sed -i "s|^;\?upload_tmp_dir =.*$|upload_tmp_dir = $DATADIR/tmp|" "/etc/php/${PHPVER}/fpm/php.ini" sed -i "s|^;\?sys_temp_dir =.*$|sys_temp_dir = $DATADIR/tmp|" "/etc/php/${PHPVER}/fpm/php.ini" # logs ncc config:system:set logfile --value="$DATADIR/nextcloud.log" # update fail2ban logpath [[ -f /etc/fail2ban/jail.conf ]] && { sed -i "s|logpath =.*|logpath = $DATADIR/nextcloud.log|" /etc/fail2ban/jail.conf pgrep fail2ban &>/dev/null && service fail2ban restart } # refresh nextcloud trusted domains bash /usr/local/bin/nextcloud-domain.sh # update the systems data-fingerprint ncc maintenance:data-fingerprint # refresh thumbnails ncc files:scan-app-data # restart PHP if needed [[ "$NEED_RESTART" == "1" ]] && { bash -c "sleep 5; source /usr/local/etc/library.sh; clear_opcache; service php${PHPVER}-fpm restart" &>/dev/null & }