NextcloudBackup.sh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #!/bin/bash
  2. #
  3. # Bash script for creating backups of Nextcloud.
  4. #
  5. # Version 3.0.3
  6. #
  7. # Requirements:
  8. # - pigz (https://zlib.net/pigz/) for using backup compression. If not available, you can use another compression algorithm (e.g. gzip)
  9. #
  10. # Supported database systems:
  11. # - MySQL/MariaDB
  12. # - PostgreSQL
  13. #
  14. # Usage:
  15. # - With backup directory specified in the script: ./NextcloudBackup.sh
  16. # - With backup directory specified by parameter: ./NextcloudBackup.sh <backupDirectory> (e.g. ./NextcloudBackup.sh /media/hdd/nextcloud_backup)
  17. #
  18. # 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/
  19. #
  20. # Make sure the script exits when any command fails
  21. set -Eeuo pipefail
  22. # Variables
  23. working_dir=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
  24. configFile="${working_dir}/NextcloudBackupRestore.conf" # Holds the configuration for NextcloudBackup.sh and NextcloudRestore.sh
  25. _backupMainDir=${1:-}
  26. # Function for error messages
  27. errorecho() { cat <<< "$@" 1>&2; }
  28. #
  29. # Check if config file exists
  30. #
  31. if [ ! -f "${configFile}" ]
  32. then
  33. errorecho "ERROR: Configuration file $configFile cannot be found!"
  34. errorecho "Please make sure that a configuratrion file '$configFile' is present in the main directory of the scripts."
  35. errorecho "This file can be created automatically using the setup.sh script."
  36. exit 1
  37. fi
  38. source "$configFile" || exit 1 # Read configuration variables
  39. if [ -n "$_backupMainDir" ]; then
  40. backupMainDir=$(echo $_backupMainDir | sed 's:/*$::')
  41. fi
  42. currentDate=$(date +"%Y%m%d_%H%M%S")
  43. # The actual directory of the current backup - this is a subdirectory of the main directory above with a timestamp
  44. backupDir="${backupMainDir}/${currentDate}"
  45. function DisableMaintenanceMode() {
  46. echo "$(date +"%H:%M:%S"): Switching off maintenance mode..."
  47. sudo -u "${webserverUser}" php ${nextcloudFileDir}/occ maintenance:mode --off
  48. echo "Done"
  49. echo
  50. }
  51. # Capture CTRL+C
  52. trap CtrlC INT
  53. function CtrlC() {
  54. read -p "Backup cancelled. Keep maintenance mode? [y/n] " -n 1 -r
  55. echo
  56. if ! [[ $REPLY =~ ^[Yy]$ ]]
  57. then
  58. DisableMaintenanceMode
  59. else
  60. echo "Maintenance mode still enabled."
  61. fi
  62. echo "Starting web server..."
  63. systemctl start "${webserverServiceName}"
  64. echo "Done"
  65. echo
  66. exit 1
  67. }
  68. #
  69. # Print information
  70. #
  71. echo "Backup directory: ${backupMainDir}"
  72. #
  73. # Check for root
  74. #
  75. if [ "$(id -u)" != "0" ]
  76. then
  77. errorecho "ERROR: This script has to be run as root!"
  78. exit 1
  79. fi
  80. #
  81. # Check if backup dir already exists
  82. #
  83. if [ ! -d "${backupDir}" ]
  84. then
  85. mkdir -p "${backupDir}"
  86. else
  87. errorecho "ERROR: The backup directory ${backupDir} already exists!"
  88. exit 1
  89. fi
  90. #
  91. # Set maintenance mode
  92. #
  93. echo "$(date +"%H:%M:%S"): Set maintenance mode for Nextcloud..."
  94. sudo -u "${webserverUser}" php ${nextcloudFileDir}/occ maintenance:mode --on
  95. echo "Done"
  96. echo
  97. #
  98. # Stop web server
  99. #
  100. echo "$(date +"%H:%M:%S"): Stopping web server..."
  101. systemctl stop "${webserverServiceName}"
  102. echo "Done"
  103. echo
  104. #
  105. # Backup file directory
  106. #
  107. echo "$(date +"%H:%M:%S"): Creating backup of Nextcloud file directory..."
  108. if [ "$useCompression" = true ] ; then
  109. `$compressionCommand "${backupDir}/${fileNameBackupFileDir}" -C "${nextcloudFileDir}" .`
  110. else
  111. tar -cpf "${backupDir}/${fileNameBackupFileDir}" -C "${nextcloudFileDir}" .
  112. fi
  113. echo "Done"
  114. echo
  115. #
  116. # Backup data directory
  117. #
  118. echo "$(date +"%H:%M:%S"): Creating backup of Nextcloud data directory..."
  119. if [ "$includeUpdaterBackups" = false ] ; then
  120. echo "Ignoring Nextcloud updater backup directory"
  121. if [ "$useCompression" = true ] ; then
  122. `$compressionCommand "${backupDir}/${fileNameBackupDataDir}" --exclude="updater-*/backups/*" -C "${nextcloudDataDir}" .`
  123. else
  124. tar -cpf "${backupDir}/${fileNameBackupDataDir}" --exclude="updater-*/backups/*" -C "${nextcloudDataDir}" .
  125. fi
  126. else
  127. if [ "$useCompression" = true ] ; then
  128. `$compressionCommand "${backupDir}/${fileNameBackupDataDir}" -C "${nextcloudDataDir}" .`
  129. else
  130. tar -cpf "${backupDir}/${fileNameBackupDataDir}" -C "${nextcloudDataDir}" .
  131. fi
  132. fi
  133. echo "Done"
  134. echo
  135. #
  136. # Backup local external storage.
  137. #
  138. if [ ! -z "${nextcloudLocalExternalDataDir+x}" ] ; then
  139. echo "$(date +"%H:%M:%S"): Creating backup of Nextcloud local external storage directory..."
  140. if [ "$useCompression" = true ] ; then
  141. `$compressionCommand "${backupDir}/${fileNameBackupExternalDataDir}" -C "${nextcloudLocalExternalDataDir}" .`
  142. else
  143. tar -cpf "${backupDir}/${fileNameBackupExternalDataDir}" -C "${nextcloudLocalExternalDataDir}" .
  144. fi
  145. echo "Done"
  146. echo
  147. fi
  148. #
  149. # Backup DB
  150. #
  151. if [ "${databaseSystem,,}" = "mysql" ] || [ "${databaseSystem,,}" = "mariadb" ]; then
  152. echo "$(date +"%H:%M:%S"): Backup Nextcloud database (MySQL/MariaDB)..."
  153. if ! [ -x "$(command -v mysqldump)" ]; then
  154. errorecho "ERROR: MySQL/MariaDB not installed (command mysqldump not found)."
  155. errorecho "ERROR: No backup of database possible!"
  156. else
  157. mysqldump --single-transaction -h localhost -u "${dbUser}" -p"${dbPassword}" "${nextcloudDatabase}" > "${backupDir}/${fileNameBackupDb}"
  158. fi
  159. echo "Done"
  160. echo
  161. elif [ "${databaseSystem,,}" = "postgresql" ] || [ "${databaseSystem,,}" = "pgsql" ]; then
  162. echo "$(date +"%H:%M:%S"): Backup Nextcloud database (PostgreSQL)..."
  163. if ! [ -x "$(command -v pg_dump)" ]; then
  164. errorecho "ERROR: PostgreSQL not installed (command pg_dump not found)."
  165. errorecho "ERROR: No backup of database possible!"
  166. else
  167. PGPASSWORD="${dbPassword}" pg_dump "${nextcloudDatabase}" -h localhost -U "${dbUser}" -f "${backupDir}/${fileNameBackupDb}"
  168. fi
  169. echo "Done"
  170. echo
  171. fi
  172. #
  173. # Start web server
  174. #
  175. echo "$(date +"%H:%M:%S"): Starting web server..."
  176. systemctl start "${webserverServiceName}"
  177. echo "Done"
  178. echo
  179. #
  180. # Disable maintenance mode
  181. #
  182. DisableMaintenanceMode
  183. #
  184. # Delete old backups
  185. #
  186. if [ ${maxNrOfBackups} != 0 ]
  187. then
  188. nrOfBackups=$(ls -l ${backupMainDir} | grep -c ^d)
  189. if [ ${nrOfBackups} -gt ${maxNrOfBackups} ]
  190. then
  191. echo "$(date +"%H:%M:%S"): Removing old backups..."
  192. ls -t ${backupMainDir} | tail -$(( nrOfBackups - maxNrOfBackups )) | while read -r dirToRemove; do
  193. echo "${dirToRemove}"
  194. rm -r "${backupMainDir}/${dirToRemove:?}"
  195. echo "Done"
  196. echo
  197. done
  198. fi
  199. fi
  200. echo
  201. echo "DONE!"
  202. echo "$(date +"%H:%M:%S"): Backup created: ${backupDir}"