freedombone-backup-local 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # Backup to local storage - typically a USB drive
  12. # License
  13. # =======
  14. #
  15. # Copyright (C) 2015-2016 Bob Mottram <bob@robotics.uk.to>
  16. #
  17. # This program is free software: you can redistribute it and/or modify
  18. # it under the terms of the GNU Affero General Public License as published by
  19. # the Free Software Foundation, either version 3 of the License, or
  20. # (at your option) any later version.
  21. #
  22. # This program is distributed in the hope that it will be useful,
  23. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. # GNU Affero General Public License for more details.
  26. #
  27. # You should have received a copy of the GNU Affero General Public License
  28. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  29. PROJECT_NAME='freedombone'
  30. COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt
  31. BACKUP_EXTRA_DIRECTORIES=/root/backup-extra-dirs.csv
  32. ENABLE_BACKUP_VERIFICATION="no"
  33. export TEXTDOMAIN=${PROJECT_NAME}-backup-local
  34. export TEXTDOMAINDIR="/usr/share/locale"
  35. # include utils which allow function_check and drive mount
  36. UTILS_FILES=/usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-*
  37. for f in $UTILS_FILES
  38. do
  39. source $f
  40. done
  41. USB_DRIVE=/dev/sdb1
  42. USB_MOUNT=/mnt/usb
  43. # get default USB from config file
  44. CONFIG_FILE=$HOME/${PROJECT_NAME}.cfg
  45. if [ -f $CONFIG_FILE ]; then
  46. if grep -q "USB_DRIVE=" $CONFIG_FILE; then
  47. USB_DRIVE=$(cat $CONFIG_FILE | grep "USB_DRIVE=" | awk -F '=' '{print $2}')
  48. fi
  49. fi
  50. # get the version of Go being used
  51. GO_VERSION=$(cat /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-go | grep 'GO_VERSION=' | head -n 1 | awk -F '=' '{print $2}')
  52. GVM_HOME=$(cat /usr/share/${PROJECT_NAME}/utils/${PROJECT_NAME}-utils-go | grep 'GVM_HOME=' | head -n 1 | awk -F '=' '{print $2}')
  53. ADMIN_USERNAME=
  54. ADMIN_NAME=
  55. # The name of a currently suspended site
  56. # Sites are suspended so that verification should work
  57. SUSPENDED_SITE=
  58. DATABASE_PASSWORD=''
  59. if [ -f /root/dbpass ]; then
  60. DATABASE_PASSWORD=$(cat /root/dbpass)
  61. fi
  62. function make_backup_directory {
  63. # make a backup directory on the drive
  64. if [ ! -d $USB_MOUNT/backup ]; then
  65. mkdir $USB_MOUNT/backup
  66. fi
  67. if [ ! -d $USB_MOUNT/backup ]; then
  68. echo $"There was a problem making the directory $USB_MOUNT/backup."
  69. umount $USB_MOUNT
  70. rm -rf $USB_MOUNT
  71. exit 3
  72. fi
  73. }
  74. function check_storage_space_remaining {
  75. # Check space remaining on the usb drive
  76. used_percent=$(df -k $USB_MOUNT | tail -n 1 | awk -F ' ' '{print $5}' | awk -F '%' '{print $1}')
  77. if [ $used_percent -gt 95 ]; then
  78. echo $"Less than 5% of space remaining on backup drive"
  79. umount $USB_MOUNT
  80. rm -rf $USB_MOUNT
  81. exit 4
  82. fi
  83. }
  84. function backup_users {
  85. # Backup user files
  86. for d in /home/*/ ; do
  87. USERNAME=$(echo "$d" | awk -F '/' '{print $3}')
  88. if [[ $(is_valid_user "$USERNAME") == "1" ]]; then
  89. # Backup any gpg keys
  90. if [ -d /home/$USERNAME/.gnupg ]; then
  91. echo $"Backing up gpg keys for $USERNAME"
  92. backup_directory_to_usb /home/$USERNAME/.gnupg gnupg/$USERNAME
  93. fi
  94. # Backup any personal settings
  95. if [ -d /home/$USERNAME/personal ]; then
  96. echo $"Backing up personal settings for $USERNAME"
  97. backup_directory_to_usb /home/$USERNAME/personal personal/$USERNAME
  98. fi
  99. # Backup ssh keys
  100. if [ -d /home/$USERNAME/.ssh ]; then
  101. echo $"Backing up ssh keys for $USERNAME"
  102. backup_directory_to_usb /home/$USERNAME/.ssh ssh/$USERNAME
  103. fi
  104. # Backup fin database if it exists
  105. if [ -d /home/$USERNAME/.fin ]; then
  106. echo $"Backing up fin files for $USERNAME"
  107. backup_directory_to_usb /home/$USERNAME/.fin fin/$USERNAME
  108. fi
  109. # Backup emacs
  110. if [ -d /home/$USERNAME/.emacs.d ]; then
  111. echo $"Backing up Emacs config for $USERNAME"
  112. if [ -f /home/$USERNAME/.emacs ]; then
  113. cp /home/$USERNAME/.emacs /home/$USERNAME/.emacs.d/dotemacs
  114. fi
  115. backup_directory_to_usb /home/$USERNAME/.emacs.d config/$USERNAME
  116. fi
  117. # Backup user configs
  118. if [ -d /home/$USERNAME/.config ]; then
  119. echo $"Backing up config files for $USERNAME"
  120. backup_directory_to_usb /home/$USERNAME/.config config/$USERNAME
  121. fi
  122. # Backup monkeysphere
  123. if [ -d /home/$USERNAME/.monkeysphere ]; then
  124. echo $"Backing up monkeysphere files for $USERNAME"
  125. backup_directory_to_usb /home/$USERNAME/.monkeysphere monkeysphere/$USERNAME
  126. fi
  127. # Backup user local
  128. if [ -d /home/$USERNAME/.local ]; then
  129. echo $"Backing up local files for $USERNAME"
  130. backup_directory_to_usb /home/$USERNAME/.local local/$USERNAME
  131. fi
  132. # Backup mutt
  133. if [ -f /home/$USERNAME/.muttrc ]; then
  134. echo $"Backing up Mutt settings for $USERNAME"
  135. if [ ! -d /home/$USERNAME/tempbackup ]; then
  136. mkdir -p /home/$USERNAME/tempbackup
  137. fi
  138. cp /home/$USERNAME/.muttrc /home/$USERNAME/tempbackup
  139. if [ -f /etc/Muttrc ]; then
  140. cp /etc/Muttrc /home/$USERNAME/tempbackup
  141. fi
  142. backup_directory_to_usb /home/$USERNAME/tempbackup mutt/$USERNAME
  143. fi
  144. # Backup email
  145. if [ -d /home/$USERNAME/Maildir ]; then
  146. echo $"Stopping mail server"
  147. systemctl stop exim4
  148. echo $"Creating an email archive for $USERNAME"
  149. if [ ! -d /root/tempbackupemail/$USERNAME ]; then
  150. mkdir -p /root/tempbackupemail/$USERNAME
  151. fi
  152. tar -czvf /root/tempbackupemail/$USERNAME/maildir.tar.gz /home/$USERNAME/Maildir
  153. echo $"Restarting mail server"
  154. systemctl start exim4
  155. echo $"Backing up emails for $USERNAME"
  156. backup_directory_to_usb /root/tempbackupemail/$USERNAME mail/$USERNAME
  157. fi
  158. # Backup spamassassin
  159. if [ -d /home/$USERNAME/.spamassassin ]; then
  160. echo $"Backing up spamassassin settings for $USERNAME"
  161. backup_directory_to_usb /home/$USERNAME/.spamassassin spamassassin/$USERNAME
  162. fi
  163. # Backup procmail
  164. if [ -f /home/$USERNAME/.procmailrc ]; then
  165. echo $"Backing up procmail settings for $USERNAME"
  166. if [ ! -d /home/$USERNAME/tempbackup ]; then
  167. mkdir -p /home/$USERNAME/tempbackup
  168. fi
  169. cp /home/$USERNAME/.procmailrc /home/$USERNAME/tempbackup
  170. backup_directory_to_usb /home/$USERNAME/tempbackup procmail/$USERNAME
  171. fi
  172. fi
  173. done
  174. }
  175. function backup_directories {
  176. export GVM_ROOT=$GVM_HOME
  177. if [ -d $GVM_ROOT/bin ]; then
  178. cd $GVM_ROOT/bin
  179. [[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm"
  180. gvm use go${GO_VERSION} --default
  181. systemctl set-environment GOPATH=$GOPATH
  182. fi
  183. # directories to be backed up (source,dest)
  184. backup_dirs=(
  185. "/etc/letsencrypt, letsencrypt"
  186. "/etc/ssl, ssl"
  187. "/var/spool/mlmmj, mailinglist"
  188. "/etc/nginx/sites-available, web"
  189. "/var/lib/tor, tor"
  190. )
  191. for dr in "${backup_dirs[@]}"
  192. do
  193. # if this directory exists then back it up to the given destination
  194. source_directory=$(echo $dr | awk -F ',' '{print $1}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  195. if [ -d $source_directory ]; then
  196. dest_directory=$(echo $dr | awk -F ',' '{print $2}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  197. echo $"Backing up $source_directory to $dest_directory"
  198. backup_directory_to_usb $source_directory $dest_directory
  199. fi
  200. restart_site
  201. done
  202. }
  203. function remove_backup_directory {
  204. if [ $1 ]; then
  205. if [[ $1 == "remove" ]]; then
  206. if [ -d $USB_MOUNT/backup ]; then
  207. rm -rf $USB_MOUNT/backup
  208. echo $'Existing backup directory removed'
  209. backup_unmount_drive
  210. exit 0
  211. fi
  212. fi
  213. fi
  214. }
  215. function prepare_directories {
  216. export GVM_ROOT=$GVM_HOME
  217. if [ -d $GVM_ROOT/bin ]; then
  218. cd $GVM_ROOT/bin
  219. [[ -s "$GVM_ROOT/scripts/gvm" ]] && source "$GVM_ROOT/scripts/gvm"
  220. gvm use go${GO_VERSION} --default
  221. systemctl set-environment GOPATH=$GOPATH
  222. fi
  223. # Some miscellaneous preparation for backing up directories
  224. if [ -d $GOPATH/src/github.com/gogits ]; then
  225. mv /home/git/gogs-repositories/*.git /home/git/gogs-repositories/$ADMIN_USERNAME
  226. fi
  227. if [ -d /var/lib/tox-bootstrapd ]; then
  228. cp /etc/tox-bootstrapd.conf /var/lib/tox-bootstrapd
  229. if [ -d /var/lib/tox-bootstrapd/Maildir ]; then
  230. rm -rf /var/lib/tox-bootstrapd/Maildir
  231. fi
  232. fi
  233. }
  234. function backup_configuration {
  235. echo $"Backing up ${PROJECT_NAME} configuration files"
  236. temp_backup_dir=/root/tempbackupconfig
  237. if [ ! -d $temp_backup_dir ]; then
  238. mkdir -p $temp_backup_dir
  239. fi
  240. cp -f $CONFIG_FILE $temp_backup_dir
  241. cp -f $COMPLETION_FILE $temp_backup_dir
  242. if [ -f $BACKUP_EXTRA_DIRECTORIES ]; then
  243. cp -f $BACKUP_EXTRA_DIRECTORIES $temp_backup_dir
  244. fi
  245. # nginx password hashes
  246. if [ -f /etc/nginx/.htpasswd ]; then
  247. cp -f /etc/nginx/.htpasswd $temp_backup_dir/htpasswd
  248. fi
  249. backup_directory_to_usb $temp_backup_dir config
  250. }
  251. function backup_admin_readme {
  252. if [ -f /home/$ADMIN_USERNAME/README ]; then
  253. echo $"Backing up README"
  254. temp_backup_dir=/home/$ADMIN_USERNAME/tempbackup
  255. if [ ! -d $temp_backup_dir ]; then
  256. mkdir -p $temp_backup_dir
  257. fi
  258. cp -f /home/$ADMIN_USERNAME/README $temp_backup_dir
  259. backup_directory_to_usb $temp_backup_dir readme
  260. fi
  261. }
  262. function backup_mariadb {
  263. if [ ${#DATABASE_PASSWORD} -gt 1 ]; then
  264. temp_backup_dir=/root/tempmariadb
  265. if [ ! -d $temp_backup_dir ]; then
  266. mkdir $temp_backup_dir
  267. fi
  268. mysqldump --lock-tables --password="$DATABASE_PASSWORD" mysql user > $temp_backup_dir/mysql.sql
  269. if [ ! -s $temp_backup_dir/mysql.sql ]; then
  270. echo $"Unable to backup mysql settings"
  271. rm -rf $temp_backup_dir
  272. umount $USB_MOUNT
  273. rm -rf $USB_MOUNT
  274. exit 8
  275. fi
  276. echo "$DATABASE_PASSWORD" > $temp_backup_dir/db
  277. chmod 400 $temp_backup_dir/db
  278. backup_directory_to_usb $temp_backup_dir mariadb
  279. fi
  280. }
  281. function valid_backup_destination {
  282. destination_dir="$1"
  283. is_valid="yes"
  284. if [[ "$destination_dir" == "hubzilla" || \
  285. "$destination_dir" == "hubzilladata" || \
  286. "$destination_dir" == "gogs" || \
  287. "$destination_dir" == "gogsrepos" || \
  288. "$destination_dir" == "gogsssh" || \
  289. "$destination_dir" == "gnusocial" || \
  290. "$destination_dir" == "gnusocialdata" || \
  291. "$destination_dir" == "mariadb" || \
  292. "$destination_dir" == "config" || \
  293. "$destination_dir" == "letsencrypt" || \
  294. "$destination_dir" == "wiki" || \
  295. "$destination_dir" == "wiki2" || \
  296. "$destination_dir" == "xmpp" || \
  297. "$destination_dir" == "ipfs" || \
  298. "$destination_dir" == "dlna" || \
  299. "$destination_dir" == "tox" || \
  300. "$destination_dir" == "ssl" || \
  301. "$destination_dir" == "ttrss" || \
  302. "$destination_dir" == "blog" || \
  303. "$destination_dir" == "syncthingconfig" || \
  304. "$destination_dir" == "syncthingshared" || \
  305. "$destination_dir" == "syncthing" || \
  306. "$destination_dir" == "mediagoblin" || \
  307. "$destination_dir" == "mailinglist" ]]; then
  308. is_valid="no"
  309. fi
  310. echo $is_valid
  311. }
  312. function backup_extra_directories {
  313. if [ ! -f $BACKUP_EXTRA_DIRECTORIES ]; then
  314. return
  315. fi
  316. echo $"Backing up some additional directories"
  317. while read backup_line
  318. do
  319. backup_dir=$(echo "$backup_line" | awk -F ',' '{print $1}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  320. if [ -d "$backup_dir" ]; then
  321. destination_dir=$(echo "$backup_line" | awk -F ',' '{print $2}' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  322. if [[ $(valid_backup_destination "$destination_dir") == "yes" ]]; then
  323. backup_directory_to_usb "$backup_dir" "$destination_dir"
  324. else
  325. echo $"WARNING: The backup directory $destination_dir is already used."
  326. echo $"Choose a different destination name for backing up $backup_dir"
  327. fi
  328. else
  329. echo $"WARNING: Directory $backup_dir does not exist"
  330. fi
  331. done <$BACKUP_EXTRA_DIRECTORIES
  332. }
  333. # has the remove option been set ?
  334. remove_option=$2
  335. if [[ $1 == "remove" ]]; then
  336. remove_option=$1
  337. fi
  338. backup_mount_drive $1 $2
  339. remove_backup_directory $remove_option
  340. make_backup_directory
  341. check_storage_space_remaining
  342. backup_users
  343. prepare_directories
  344. backup_directories
  345. backup_apps local
  346. backup_configuration
  347. backup_admin_readme
  348. backup_mariadb
  349. backup_extra_directories
  350. backup_unmount_drive $USB_DRIVE $USB_MOUNT
  351. echo $"Backup to USB drive is complete. You can now unplug it."
  352. exit 0