backup-server 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #!/bin/bash
  2. #/###################################################################\
  3. #| Make backup of castanedo.es server compressed with: |
  4. #| -Gzip |
  5. #| -Bzip2 |
  6. #| -XZ |
  7. #| -7zip |
  8. #| and encrypt it. |
  9. #| |
  10. #| Guzmán Castanedo (guzman@castanedo.es) |
  11. #| Version 1.9 (March 2018) |
  12. #| Licence: GPL v3.0 -> https://www.gnu.org/licenses/gpl-3.0.en.html |
  13. #\###################################################################/
  14. function usage {
  15. printf "%s Version 1.9\n" $(basename $0)
  16. printf "Usage: %s [options]... -z|-j|-J \n" $(basename $0)
  17. printf "Make a encrypted backup of a server compressed with: \n"
  18. printf "\t·Gzip (tar.gz or tar.gz.gpg)\n"
  19. printf "\t·Bzip2 (tar.bz2 or tar.gz.gpg)\n"
  20. printf "\t·XZ (tar.xz or tar.xz.gpg)\n"
  21. printf "\t·7Z (7z)\n"
  22. printf "\n"
  23. printf "Backup Options:\n"
  24. printf "\t-d, --directory dir: backup directory\n"
  25. printf "\t\tDefault: %s\n" $backupDir
  26. printf "\t-p, --prefix name: prefix for the name of the backup\n"
  27. printf "\t\tDefault: %s\n" $backupPrefix
  28. printf "\t--no-postfix: disable the postfi: the full name will be the prefix\n"
  29. printf "\t\tDefault: prefix-yyyy-mm-dd(date)-XXXXXX(random)\n"
  30. printf "\t--no-remove: no remove old files\n"
  31. printf "\t\tDefault: false\n"
  32. printf "\t--remove-days numbet: set number of days to considere a backup old\n"
  33. printf "\t\tDefault: %s\n" $deleteDays
  34. printf "\t-u, --user uid: name of the user owner of the backup\n"
  35. printf "\t\tDefault: %s\n" $user
  36. printf "\t-g, --group gid: name of the group owner of the backup\n"
  37. printf "\t\tDefault: %s\n" $group
  38. printf "\t--permision-mask number: octal mask to set accesss permision of the backup\n"
  39. printf "\t\tDefault: %s\n" $permisionMask
  40. printf "\n"
  41. printf "Compression Options:\n"
  42. printf "\t-z, --gzip: compress using gzip (tar.gz or tar.gz.gpg)\n"
  43. printf "\t-j, --bzip2: compress using bzip2 (tar.bz2 or tar.bz2.gpg)\n"
  44. printf "\t-J, --xz: compress using xz (tar.xz or tar.xz.gpg)\n"
  45. printf "\t-7, --7zip: compress using 7z (7z)\n"
  46. printf "\n"
  47. printf "Encryption Options:\n"
  48. printf "\t-k, --key-id ID: set gpg2 public key-id used for encryption\n"
  49. printf "\t\tDefault: %s\n" $keyID
  50. printf "\t--no-encryption: disable the encryption of the backup\n"
  51. printf "\t\tDefault: %s\n" $noEncryption
  52. printf "\t--7z-password password: set password (ONLY for 7z)\n"
  53. printf "\t\tDefault: %s\n" $pass7z
  54. printf "\n"
  55. printf "Web Options:\n"
  56. printf "\t--web-dir dir: set web pages directory to backup\n"
  57. printf "\t\tDefault: %s\n" $webDir
  58. printf "\t--no-web: disable backup of web pages\n"
  59. printf "\t\tDefault: %s\n" $noWeb
  60. printf "\n"
  61. printf "SQL Options:\n"
  62. printf "\t--no-sql: disable MySQL/MAriaDB backup\n"
  63. printf "\t\tDefault: %s\n" $noSql
  64. printf "\n"
  65. printf "Nginx Options:\n"
  66. printf "\t--nginx-dir dir: set nginx configuration directory to backup\n"
  67. printf "\t\tDefault: %s\n" $nginxDir
  68. printf "\t--no-nginx: disable Nginx backup\n"
  69. printf "\t\tDefault: %s\n" $noNginx
  70. printf "\n"
  71. printf "Let's Encrypt Options:\n"
  72. printf "\t--letsencrypt-dir dir: set Let's Encrypt configuration directory to backup\n"
  73. printf "\t\tDefault: %s\n" $letsencryptDir
  74. printf "\t--no-letsencrypt: disable Let's Encrypt backup\n"
  75. printf "\t\tDefault: %s\n" $noLetsencrypt
  76. printf "\n"
  77. printf "Mail Options:\n"
  78. printf "\t--mail-dir dir: set Mailboxes directory to backup\n"
  79. printf "\t\tDefault: %s\n" $mailDir
  80. printf "\t\t--no-mail: disable mailboxes backup\n"
  81. printf "\t\tDefault: %s\n" $noMail
  82. printf "\n"
  83. printf "Home Options:\n"
  84. printf "\t--home-dir dir: set home directories to backup\n"
  85. printf "\t\tDefault: %s\n" $homeDir
  86. printf "\t--no-home: disable home directory backup\n"
  87. printf "\t\tDefault: %s\n" $noHome
  88. printf "\n"
  89. printf "GOGS Options:\n"
  90. printf "\t--gogs-dir dir: set GOGS Repository to backup\n"
  91. printf "\t\tDefault: %s\n" $gogsDir
  92. printf "\t--no-gogs: disable gogs backup\n"
  93. printf "\t\tDefault: %s\n" $noGogs
  94. exit
  95. }
  96. function makep7zip {
  97. #Destination file
  98. ext=".7z"
  99. backupOutput=$backupOutput$ext
  100. printf "Backup File (7z):\t%s\n" $backupOutput
  101. #Copy webpages code (except backup and main/public)
  102. if [ $noWeb = false ] && [ -d $webDir ];then
  103. printf "Compressing:\t%s\n" $webDir
  104. #cd /usr/share/nginx
  105. tempfile=$(mktemp -t exclude-XXX)
  106. echo "www/backup" > $tempfile
  107. echo "www/main/public" >> $tempfile
  108. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $webDir -x@$tempfile > /dev/null
  109. if [ $? != 0 ];then
  110. printf "WARNING:\tError copying web pages (Continue).\n"
  111. fi
  112. rm $tempfile
  113. fi
  114. #Copy MySQL databases (mysqldump)
  115. if [ $noSql = false ] && [ -x "$(which mysql)" ] && [ -x "$(which mysqldump)" ]; then
  116. list=$(mysql -u $mysqluser -p$mysqlpass -e "show DATABASES;")
  117. #Parse databases expect information_schema & performance_schema
  118. for database in $list; do
  119. valid=true
  120. for excep in Database information_schema performance_schema; do
  121. if [ $database = $excep ]; then
  122. valid=false
  123. break
  124. fi
  125. done
  126. if [ $valid = true ]; then
  127. printf "Compressing MySQL database:\t%s\n" $database.sql
  128. mysqldump -u $mysqluser -p$mysqlpass $database | 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput -simysql/$database.sql > /dev/null 2>&1
  129. if [ $? != 0 ];then
  130. printf "WARNING:\tError compressing database (%s) (Continue).\n" $database
  131. fi
  132. fi
  133. done
  134. fi
  135. #Copy nginx configuration (sites-available)
  136. if [ $noNginx = false ] && [ -d $nginxDir ];then
  137. printf "Compressing:\t%s\n" $nginxDir
  138. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $nginxDir > /dev/null
  139. if [ $? != 0 ];then
  140. printf "WARNING:\tError copying nginx configuration (Continue)\n"
  141. fi
  142. fi
  143. #Copy Email (this could be heavy in the future)
  144. if [ $noMail = false ] && [ -d $mailDir ];then
  145. printf "Compressing:\t%s\n" $mailDir
  146. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $mailDir > /dev/null
  147. #tar -c -zf - $mailDir | 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput -simail.tar.gz > /dev/null
  148. if [ $? != 0 ];then
  149. printf "WARNING:\tError copying mailboxes (Continue)\n"
  150. fi
  151. fi
  152. #Copy Certificates (LetsEncrypt)
  153. if [ $noLetsencrypt = false ] && [ -d $letsencryptDir ];then
  154. printf "Compressing:\t%s\n" $letsencryptDir
  155. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $letsEncryptDir > /dev/null
  156. if [ $? != 0 ];then
  157. printf "WARNING:\tError copying Let's Encrypt certificates (Continue)\n"
  158. fi
  159. fi
  160. #Copy /home
  161. if [ $noHome = false ] && [ -d $homeDir ];then
  162. printf "Compressing:\t%s\n" $homeDir
  163. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $homeDir > /dev/null
  164. if [ $? != 0 ];then
  165. printf "WARNING:\tError copying home dir (Continue)\n"
  166. fi
  167. fi
  168. #Copy GOGS
  169. if [ $noGogs = false ] && [ -d $gogsDir ];then
  170. printf "Compressing:\t%s\n" $gogsDir
  171. 7z a -t7z -mx=9 -p$pass7z -mhe $backupOutput $gogsDir > /dev/null
  172. if [ $? != 0 ];then
  173. printf "WARNING:\tError copying GOGS Repository (Continue)\n"
  174. fi
  175. fi
  176. }
  177. function makeTar {
  178. #Destination file
  179. printf "Backup File:\t%s\n" $backupOutput.tar.gz.gpg
  180. #Copy webpages code (except backup and main/public)
  181. if [ $noWeb = false ] && [ -d $webDir ];then
  182. printf "Adding:\t%s\n" $webDir
  183. tar -rf $tempOutput -C $(dirname $webDir) --exclude=www/backup --exclude=www/main/public $(basename $webDir) > /dev/null 2>&1
  184. if [ $? != 0 ]; then
  185. printf "WARNING:\tError copying web pages (Continue).\n"
  186. fi
  187. fi
  188. #Copy MySQL databases (mysqldump)
  189. if [ $noSql = false ] && [ -x "$(which mysql)" ] && [ -x "$(which mysqldump)" ]; then
  190. list=$(mysql -u $mysqluser -p$mysqlpass -e "show DATABASES;" 2> /dev/null)
  191. mkdir /tmp/mysql
  192. #Parse databases expect information_schema & performance_schema
  193. for database in $list; do
  194. valid=true
  195. for excep in Database information_schema performance_schema; do
  196. if [ $database = $excep ]; then
  197. valid=false
  198. break
  199. fi
  200. done
  201. if [ $valid = true ]; then
  202. printf "Adding MySQL database:\t%s\n" $database.sql
  203. mysqldump -u $mysqluser -p$mysqlpass $database > /tmp/mysql/$database.sql 2> /dev/null
  204. if [ $? != 0 ];then
  205. printf "WARNING:\tError extracting database (%s) (Continue).\n" $database
  206. continue
  207. fi
  208. tar -rf $tempOutput -C /tmp mysql/$database.sql > /dev/null 2>&1
  209. if [ $? != 0 ];then
  210. printf "WARNING:\tError adding to tar (%s) (Continue)\n"
  211. fi
  212. rm /tmp/mysql/$database.sql
  213. fi
  214. done
  215. rmdir /tmp/mysql
  216. fi
  217. #Copy nginx configuration (sites-available)
  218. if [ $noNginx = false ] && [ -d $nginxDir ];then
  219. printf "Adding:\t%s\n" $nginxDir
  220. tar -rf $tempOutput -C $(dirname $nginxDir) $(basename $nginxDir) > /dev/null 2>&1
  221. if [ $? != 0 ];then
  222. printf "WARNING:\tError copying nginx configuration (Continue)\n"
  223. fi
  224. fi
  225. #Copy Email (this could be heavy in the future)
  226. if [ $noMail = false ] && [ -d $mailDir ];then
  227. printf "Adding:\t%s\n" $mailDir
  228. tar -rf $tempOutput -C $(dirname $mailDir) $(basename $mailDir) > /dev/null 2>&1
  229. if [ $? != 0 ];then
  230. printf "WARNING:\tError copying mailboxes (Continue)\n"
  231. fi
  232. fi
  233. #Copy Certificates (LetsEncrypt)
  234. if [ $noLetsencrypt = false ] && [ -d $letsencryptDir ];then
  235. printf "Adding:\t%s\n" $letsencryptDir
  236. tar -rf $tempOutput -C $(dirname $letsencryptDir) $(basename $letsencryptDir) > /dev/null 2>&1
  237. if [ $? != 0 ];then
  238. printf "WARNING:\tError copying Let's Encrypt certificates (Continue)\n"
  239. fi
  240. fi
  241. #Copy /home
  242. if [ $noHome = false ] && [ -d $homeDir ];then
  243. printf "Adding:\t%s\n" $homeDir
  244. tar -rf $tempOutput -C $(dirname $homeDir) $(basename $homeDir) > /dev/null 2>&1
  245. if [ $? != 0 ];then
  246. printf "WARNING:\tError copying home dir (Continue)\n"
  247. fi
  248. fi
  249. #Copy GOGS
  250. if [ $noGogs = false ] && [ -d $gogsDir ];then
  251. printf "Adding:\t/opt/gogs\n"
  252. tar -rf $tempOutput -C $(dirname $gogsDir) $(basename $gogsDir) > /dev/null 2>&1
  253. if [ $? != 0 ];then
  254. printf "WARNING:\tError copying GOGS Repository (Continue)\n"
  255. fi
  256. fi
  257. }
  258. function gzUnencrypted {
  259. ext=".tar.gz"
  260. backupOutput=$backupOutput$ext
  261. printf "Compressing (GZIP)... %s\n" $backupOutput
  262. gzip -9 --stdout $tempOutput > $backupOutput
  263. if [ $? != 0 ]; then
  264. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  265. exit 1
  266. fi
  267. rm $tempOutput
  268. }
  269. function gzEncrypted {
  270. ext=".tar.gz.gpg"
  271. backupOutput=$backupOutput$ext
  272. printf "Compressing (GZIP) and encrypting... %s\n" $backupOutput
  273. gzip -9 --stdout $tempOutput | gpg2 --no-batch --output $backupOutput --encrypt -r $keyID -
  274. if [ $? != 0 ]; then
  275. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  276. exit 1
  277. fi
  278. rm $tempOutput
  279. }
  280. function bz2Unencrypted {
  281. ext=".tar.bz2"
  282. backupOutput=$backupOutput$ext
  283. printf "Compressing (BZIP2)... %s\n" $backupOutput
  284. bzip2 -9 --stdout $tempOutput > $backupOutput
  285. if [ $? != 0 ]; then
  286. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  287. exit 1
  288. fi
  289. rm $tempOutput
  290. }
  291. function bz2Encrypted {
  292. ext=".tar.bz2.gpg"
  293. backupOutput=$backupOutput$ext
  294. printf "Compressing (BZIP2) and encrypting... %s\n" $backupOutput
  295. bzip2 -9 --stdout $tempOutput | gpg2 --no-batch --output $backupOutput --encrypt -r $keyID -
  296. if [ $? != 0 ]; then
  297. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  298. exit 1
  299. fi
  300. rm $tempOutput
  301. }
  302. function xzUnencrypted {
  303. ext=".tar.xz"
  304. backupOutput=$backupOutput$ext
  305. printf "Compressing (XZ)... %s\n" $backupOutput
  306. xz -9 --stdout $tempOutput > $backupOutput
  307. if [ $? != 0 ]; then
  308. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  309. exit 1
  310. fi
  311. rm $tempOutput
  312. }
  313. function xzEncrypted {
  314. ext=".tar.xz.gpg"
  315. backupOutput=$backupOutput$ext
  316. printf "Compressing (XZ) and encrypting... %s\n" $backupOutput
  317. xz -9 --stdout $tempOutput | gpg2 --no-batch --output $backupOutput --encrypt -r $keyID -
  318. if [ $? != 0 ]; then
  319. printf "ERROR:\tImpossible to compress (%s)\n" $backupOutput$ext
  320. exit 1
  321. fi
  322. rm $tempOutput
  323. }
  324. #Check root
  325. startTime=$(date +"%s")
  326. if [ $(id -u) -ne 0 ]; then
  327. printf "ERROR:\tNeed to be root :O\n"
  328. exit 1
  329. fi
  330. #Data
  331. mysqluser="root"
  332. mysqlpass="mysqlpasswd"
  333. keyID="A288A3FB"
  334. pass7z="password-for-7z"
  335. backupDir=/var/www/backup
  336. backupPrefix="backup-castanedo.es"
  337. backupName=$backupPrefix-$(date +"%Y-%m-%d")-$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 6 | head -n 1)
  338. backupOutput=$backupDir/$backupName
  339. tempOutput=/tmp/$backupName.tar
  340. deleteDays="15"
  341. user="www-data"
  342. group="www-data"
  343. #Routes
  344. webDir="/var/www"
  345. nginxDir="/etc/nginx"
  346. mailDir="/var/mail"
  347. letsencryptDir="/etc/letsencrypt"
  348. homeDir="/home"
  349. gogsDir="/opt/gogs"
  350. #Control
  351. noEncryption=false
  352. gzipOn=false
  353. bzip2On=false
  354. xzOn=true
  355. p7zipOn=false
  356. permisionMask=640
  357. removeOld=true
  358. noWeb=false
  359. noSql=false
  360. noNginx=false
  361. noMail=false
  362. noLetsencrypt=false
  363. noHome=false
  364. noGogs=false
  365. #Parse args
  366. #TEMP="$(getopt)"
  367. #usage
  368. #make tar file or 7z
  369. if [ $p7zipOn = true ];then
  370. if [ ! -x $(which 7z) ];then
  371. printf "ERROR:\tp7zip Not Installed\n"
  372. exit 1
  373. fi
  374. makep7zip
  375. else
  376. if [ ! -x $(which tar) ];then
  377. printf "ERROR:\tTAR Not Installed\n"
  378. exit 1
  379. fi
  380. makeTar
  381. fi
  382. #Compression and encryption
  383. if [ $gzipOn = true ];then
  384. if [ ! -x $(which gzip) ];then
  385. printf "ERROR:\tGzip Not Installed\n"
  386. rm $tempOutput
  387. exit 1
  388. fi
  389. if [ $noEncryption = true ] || [ ! -x $(which gpg2) ];then
  390. gzUnencrypted
  391. else
  392. gzEncrypted
  393. fi
  394. elif [ $bzip2On = true ];then
  395. if [ ! -x $(which bzip2) ];then
  396. printf "ERROR:\tBzip2 Not Installed\n"
  397. rm $tempOutput
  398. exit 1
  399. fi
  400. if [ $noEncryption = true ] || [ ! -x $(which gpg2) ];then
  401. bz2Unencrypted
  402. else
  403. bz2Encrypted
  404. fi
  405. elif [ $xzOn = true ];then
  406. if [ ! -x $(which xz) ];then
  407. printf "ERROR:\tXZ Not Installed\n"
  408. rm $tempOutput
  409. exit 1
  410. fi
  411. if [ $noEncryption = true ] || [ ! -x $(which gpg2) ];then
  412. xzUnencrypted
  413. else
  414. xzEncrypted
  415. fi
  416. elif [ $p7zipOn = true ];then
  417. #Nothing to do
  418. printf "moo" > /dev/null
  419. else
  420. printf "ERROR:\tCompression method not set\n"
  421. rm $tempOutput
  422. exit 1
  423. fi
  424. #Permissions
  425. chown $user:$group $backupOutput
  426. chmod $permisionMask $backupOutput
  427. #Remove files older than 15 days
  428. if [ $removeOld = true ];then
  429. printf "Eliminando backups antiguos (+15 dias)\n"
  430. find $backupDir -mindepth 1 -mtime +$deleteDays -type f -iname $backupPrefix*$ext -delete
  431. if [ $? != 0 ];then
  432. printf "WARNING:\tError eliminando backup's antiguos (%s dias)\n" $deleteDays
  433. fi
  434. fi
  435. #End
  436. finalTime=$(date +"%s")
  437. echo "------------------------------------------------"
  438. printf "Backup completado con exito en %s segundos :)\n" $((finalTime-startTime))
  439. echo "------------------------------------------------"