4 # Bash script for restoring backups of Nextcloud.
9 # - pigz (https://zlib.net/pigz/) for using backup compression. If not available, you can use another compression algorithm (e.g. gzip)
11 # Supported database systems:
16 # - With backup directory specified in the script: ./NextcloudRestore.sh <BackupName> (e.g. ./NextcloudRestore.sh 20170910_132703)
17 # - With backup directory specified by parameter: ./NextcloudRestore.sh <BackupName> <BackupDirectory> (e.g. ./NextcloudRestore.sh 20170910_132703 /media/hdd/nextcloud_backup)
19 # The script is based on an installation of Nextcloud using nginx and MariaDB, see https://decatec.de/home-server/nextcloud-auf-ubuntu-server-20-04-lts-mit-nginx-mariadb-php-lets-encrypt-redis-und-fail2ban/
24 # You have to customize this script (directories, users, etc.) for your actual environment.
25 # All entries which need to be customized are tagged with "TODO".
28 # Make sure the script exits when any command fails
35 if [ -z "$backupMainDir" ]; then
36 # TODO: The directory where you store the Nextcloud backups (when not specified by args)
37 backupMainDir
='/media/hdd/nextcloud_backup'
40 echo "Backup directory: $backupMainDir"
42 currentRestoreDir
="${backupMainDir}/${restore}"
44 # TODO: Set this to true, if the backup was created with compression enabled, otherwiese false.
47 # TOOD: The bare tar command for using compression.
48 # Use 'tar -xmpzf' if you want to use gzip compression.
49 compressionCommand
="tar -I pigz -xmpf"
51 # TODO: The directory of your Nextcloud installation (this is a directory under your web root)
52 nextcloudFileDir
='/var/www/nextcloud'
54 # TODO: The directory of your Nextcloud data directory (outside the Nextcloud file directory)
55 # If your data directory is located under Nextcloud's file directory (somewhere in the web root), the data directory should not be restored separately
56 nextcloudDataDir
='/var/nextcloud_data'
58 # TODO: The directory of your Nextcloud's local external storage.
59 # Uncomment if you use local external storage.
60 #nextcloudLocalExternalDataDir='/var/nextcloud_external_data'
62 # TODO: The service name of the web server. Used to start/stop web server (e.g. 'systemctl start <webserverServiceName>')
63 webserverServiceName
='nginx'
65 # TODO: Your web server user
66 webserverUser
='www-data'
68 # TODO: The name of the database system (one of: mysql, mariadb, postgresql)
69 databaseSystem
='mariadb'
71 # TODO: Your Nextcloud database name
72 nextcloudDatabase
='nextcloud_db'
74 # TODO: Your Nextcloud database user
75 dbUser
='nextcloud_db_user'
77 # TODO: The password of the Nextcloud database user
78 dbPassword
='mYpAsSw0rd'
80 # TODO: Uncomment this and set to true if the database from the backup DOES NOT use UTF8 with multibyte support (e.g. for emoijs in filenames)
83 # File names for backup files
84 # If you prefer other file names, you'll also have to change the NextcloudBackup.sh script.
85 fileNameBackupFileDir
='nextcloud-filedir.tar'
86 fileNameBackupDataDir
='nextcloud-datadir.tar'
88 if [ "$useCompression" = true
] ; then
89 fileNameBackupFileDir
='nextcloud-filedir.tar.gz'
90 fileNameBackupDataDir
='nextcloud-datadir.tar.gz'
93 fileNameBackupExternalDataDir
=''
95 if [ ! -z "${nextcloudLocalExternalDataDir+x}" ] ; then
96 fileNameBackupExternalDataDir
='nextcloud-external-datadir.tar'
98 if [ "$useCompression" = true
] ; then
99 fileNameBackupExternalDataDir
='nextcloud-external-datadir.tar.gz'
103 fileNameBackupDb
='nextcloud-db.sql'
105 # Function for error messages
106 errorecho
() { cat <<< "$@" 1>&2; }
109 # Check if parameter(s) given
111 if [ $# != "1" ] && [ $# != "2" ]
113 errorecho
"ERROR: No backup name to restore given, or wrong number of parameters!"
114 errorecho
"Usage: NextcloudRestore.sh 'BackupDate' ['BackupDirectory']"
121 if [ "$(id -u)" != "0" ]
123 errorecho
"ERROR: This script has to be run as root!"
128 # Check if backup dir exists
130 if [ ! -d "${currentRestoreDir}" ]
132 errorecho
"ERROR: Backup ${restore} not found!"
137 # Check if the commands for restoring the database are available
139 if [ "${databaseSystem,,}" = "mysql" ] ||
[ "${databaseSystem,,}" = "mariadb" ]; then
140 if ! [ -x "$(command -v mysql)" ]; then
141 errorecho
"ERROR: MySQL/MariaDB not installed (command mysql not found)."
142 errorecho
"ERROR: No restore of database possible!"
143 errorecho
"Cancel restore"
146 elif [ "${databaseSystem,,}" = "postgresql" ] ||
[ "${databaseSystem,,}" = "pgsql" ]; then
147 if ! [ -x "$(command -v psql)" ]; then
148 errorecho
"ERROR: PostgreSQL not installed (command psql not found)."
149 errorecho
"ERROR: No restore of database possible!"
150 errorecho
"Cancel restore"
156 # Set maintenance mode
158 echo "$(date +"%H
:%M
:%S
"): Set maintenance mode for Nextcloud..."
159 sudo
-u "${webserverUser}" php
${nextcloudFileDir}/occ maintenance
:mode
--on
166 echo "$(date +"%H
:%M
:%S
"): Stopping web server..."
167 systemctl stop
"${webserverServiceName}"
172 # Delete old Nextcloud directories
176 echo "$(date +"%H
:%M
:%S
"): Deleting old Nextcloud file directory..."
177 rm -r "${nextcloudFileDir}"
178 mkdir
-p "${nextcloudFileDir}"
183 echo "$(date +"%H
:%M
:%S
"): Deleting old Nextcloud data directory..."
184 rm -r "${nextcloudDataDir}"
185 mkdir
-p "${nextcloudDataDir}"
189 # Local external storage
190 if [ ! -z "${nextcloudLocalExternalDataDir+x}" ] ; then
191 echo "Deleting old Nextcloud local external storage directory..."
192 rm -r "${nextcloudLocalExternalDataDir}"
193 mkdir
-p "${nextcloudLocalExternalDataDir}"
199 # Restore file and data directory
203 echo "$(date +"%H
:%M
:%S
"): Restoring Nextcloud file directory..."
205 if [ "$useCompression" = true
] ; then
206 `$compressionCommand "${currentRestoreDir}/${fileNameBackupFileDir}" -C "${nextcloudFileDir}"`
208 tar -xmpf "${currentRestoreDir}/${fileNameBackupFileDir}" -C "${nextcloudFileDir}"
215 echo "$(date +"%H
:%M
:%S
"): Restoring Nextcloud data directory..."
217 if [ "$useCompression" = true
] ; then
218 `$compressionCommand "${currentRestoreDir}/${fileNameBackupDataDir}" -C "${nextcloudDataDir}"`
220 tar -xmpf "${currentRestoreDir}/${fileNameBackupDataDir}" -C "${nextcloudDataDir}"
226 # Local external storage
227 if [ ! -z "${nextcloudLocalExternalDataDir+x}" ] ; then
228 echo "$(date +"%H
:%M
:%S
"): Restoring Nextcloud local external storage directory..."
230 if [ "$useCompression" = true
] ; then
231 `$compressionCommand "${currentRestoreDir}/${fileNameBackupExternalDataDir}" -C "${nextcloudLocalExternalDataDir}"`
233 tar -xmpf "${currentRestoreDir}/${fileNameBackupExternalDataDir}" -C "${nextcloudLocalExternalDataDir}"
243 echo "$(date +"%H
:%M
:%S
"): Dropping old Nextcloud DB..."
245 if [ "${databaseSystem,,}" = "mysql" ] ||
[ "${databaseSystem,,}" = "mariadb" ]; then
246 mysql
-h localhost
-u "${dbUser}" -p"${dbPassword}" -e "DROP DATABASE ${nextcloudDatabase}"
247 elif [ "${databaseSystem,,}" = "postgresql" ]; then
248 sudo
-u postgres psql
-c "DROP DATABASE ${nextcloudDatabase};"
254 echo "$(date +"%H
:%M
:%S
"): Creating new DB for Nextcloud..."
256 if [ "${databaseSystem,,}" = "mysql" ] ||
[ "${databaseSystem,,}" = "mariadb" ]; then
257 if [ ! -z "${dbNoMultibyte+x}" ] && [ "${dbNoMultibyte}" = true
] ; then
258 # Database from the backup DOES NOT use UTF8 with multibyte support (e.g. for emoijs in filenames)
259 mysql
-h localhost
-u "${dbUser}" -p"${dbPassword}" -e "CREATE DATABASE ${nextcloudDatabase}"
261 # Database from the backup uses UTF8 with multibyte support (e.g. for emoijs in filenames)
262 mysql
-h localhost
-u "${dbUser}" -p"${dbPassword}" -e "CREATE DATABASE ${nextcloudDatabase} CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci"
264 elif [ "${databaseSystem,,}" = "postgresql" ] ||
[ "${databaseSystem,,}" = "pgsql" ]; then
265 sudo
-u postgres psql
-c "CREATE DATABASE ${nextcloudDatabase} WITH OWNER ${dbUser} TEMPLATE template0 ENCODING \"UNICODE\";"
271 echo "$(date +"%H
:%M
:%S
"): Restoring backup DB..."
273 if [ "${databaseSystem,,}" = "mysql" ] ||
[ "${databaseSystem,,}" = "mariadb" ]; then
274 mysql
-h localhost
-u "${dbUser}" -p"${dbPassword}" "${nextcloudDatabase}" < "${currentRestoreDir}/${fileNameBackupDb}"
275 elif [ "${databaseSystem,,}" = "postgresql" ] ||
[ "${databaseSystem,,}" = "pgsql" ]; then
276 sudo
-u postgres psql
"${nextcloudDatabase}" < "${currentRestoreDir}/${fileNameBackupDb}"
285 echo "$(date +"%H
:%M
:%S
"): Starting web server..."
286 systemctl start
"${webserverServiceName}"
291 # Set directory permissions
293 echo "$(date +"%H
:%M
:%S
"): Setting directory permissions..."
294 chown
-R "${webserverUser}":"${webserverUser}" "${nextcloudFileDir}"
295 chown
-R "${webserverUser}":"${webserverUser}" "${nextcloudDataDir}"
297 if [ ! -z "${nextcloudLocalExternalDataDir+x}" ] ; then
298 chown
-R "${webserverUser}":"${webserverUser}" "${nextcloudLocalExternalDataDir}"
305 # Disbale maintenance mode
307 echo "$(date +"%H
:%M
:%S
"): Switching off maintenance mode..."
308 sudo
-u "${webserverUser}" php
${nextcloudFileDir}/occ maintenance
:mode
--off
313 # Update the system data-fingerprint (see https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/occ_command.html#maintenance-commands-label)
315 echo "$(date +"%H
:%M
:%S
"): Updating the system data-fingerprint..."
316 sudo
-u "${webserverUser}" php
${nextcloudFileDir}/occ maintenance
:data-fingerprint
322 echo "$(date +"%H
:%M
:%S
"): Backup ${restore} successfully restored."