четверг, 22 сентября 2016 г.

Backup VPS, сайта и форума на Яндекс Диск

Впервые решился приобрести VPS у хост-провайдера и таки попробовать насколько это будет эффективнее работать, в сравнении с хостингом. Прирост производительности существенный (в моем случае), ну а остальное зависит от условий и тарифов.
Однако ключевым вопросом была не только производительность, а хранение резервных копий.
Большинство провайдеров предлагает свои автоматические системы хранения данных, в определенный (ими) период времени. Остальное, как правило - платное. Этот вариант меня не устраивал. Тем более имея под рукой целый сервер на Ubuntu - можно потрудиться, чтобы обеспечить себя достаточным количеством копий своего контента.
Поэтому я пошел собирать знания в интернете и реализовывать их на своем VPS. Под катом подробное описание того, что сделал я, чтобы сберечь свои данные на Яндекс Диске. Думаю, с другими облачными системами хранения данных - ситуация аналогичная.

Итак, задача: 



  • Хранить резервные копии необходимых БД MySql
  • Хранить копии важных системных файлов с настройками
  • Хранить Web-контент

  • Мне требуется 2 копии: 6:30 и 23:30 каждый день, в течении месяца
  • Копии старше 30 дней - необходимо удалять

  • Место хранения Yandex Disk

  • Уведомление, в случае сбоев или ошибок (над этим я еще работаю)

Для всего этого потребуется: 


  1. Яндекс Диск с необходимым доступным местом под резервные копии (расчет индивидуальный, поэтому я его тут не привожу) 
  2. VPS на Ubuntu с подключенным /dev/fuse в ядре (уточнять у провайдера, в случае проблем. см.ниже)


YD

Для начала выделим на ЯД планируемую архитектуру хранения.
Я решил не усложнять. Поэтому создал в корне папки MyDomains/Backup/DB и MyDomains/Backup/FS
Назначение каждой папки очевидно.
В папке MyDomains/Backup необходимо создать текстовый файл: FileForDetectUPLINK.txt (позже объясню для чего)

WebDav Яндекс Диска + VPS

Основной момент настройки - это монтирование папки ЯД на нашем сервере. Я использовал davfs2 И столкнулся со сложностью того, что /dev/fuse у меня не работал т.к. просто отсутствовал. Но обращение в ТП хостинг-провайдера решил этот вопрос и мне подключили fuse.

Устанавливаем davfs2

 apt-get install davfs2 
При установке нас спросит - разрешить ли доступ к монтированию пользователям без root прав. Если у вас именно так - соглашайтесь. У меня монтирование проходит под root - поэтому мне не принципиально.


Если по каким-то причинам запроса не было или вы захотели изменить свое решение:
 dpkg-reconfigure davfs2 

(не проверено мною) но вроде как для монтирования без необходимости ввода пароля root (в случае пользователей - можно добавить пользователя (который будет выполнять монтирование) в группу davfs2 командой:
 usermod -aG davfs2 MOYuser 
(-aG говорит о том, что это будет вторичная группа и состав групп в которых пользователь уже имеется - не будет изменен)

Теперь необходимо создать директорию, в которую будем монтировать YD. Например:
 mkdir /home/root/YD 

Чтобы не вводить пароль каждый раз при монтировании - необходимо добавить учетные данные в специальный файл:
 nano /etc/davfs2/secrets 
(этот файл системный и прочитать его сможет только пользователь root. Но можно создать и свой файл, если вам это требуется.) touch /home/MOYuser/.davfs2/secrets 
Теперь в файле добавим строчку:
 https://webdav.yandex.ru/MyDomains/Backup user_yandex "Parol_ot_Y@nd3xa" 
(пароль лучше взять в кавычки. Т.к. если он имеет спец символы или пробелы - это сделать просто необходимо)
Сохраняем файл.

Настройки монтирования:

 nano /etc/fstab 
Дополним этот файл строкой:
 https://webdav.yandex.ru/MyDomains/Backup /home/root/YD davfs user,rw,_netdev 0 0 
(здесь "_netdev" будет обозначать автоматическое монтирование при загрузке системы, в то время как "noauto" вместо него - не будет монтировать автоматом и придется это осуществлять вручную)
Пути должны соответствовать тем, что вы создали и указывали ранее.
Сохраняем файл и теперь можно проверить монтирование:
 mount https://webdav.yandex.ru/MyDomains/Backup 
(именно на этом этапе вы и узнаете - работает ли у вас возможность монтировать fuse системы. У меня изначально были ошибки вот такого рода:
/sbin/mount.davfs: loading kernel module fuse
/sbin/mount.davfs: loading kernel module fuse failed /sbin/mount.davfs: waiting for /dev/fuse to be created /sbin/mount.davfs: can't open fuse device /sbin/mount.davfs: trying coda kernel file system /sbin/mount.davfs: no free coda device to mount root@ovz1:/home/root# modprobe: ERROR: ../libkmod/libkmod.c:514 lookup_builtin_file() could not open builtin file '/lib/modules/
Если вы наблюдаете подобное - вам к провайдеру-поставщику. 
После-же исправления монтирование будет успешным. Теперь можно проверить подключенную папку:
 dir /home/root/YD 
в ней вы должны наблюдать: lost+found и ваш файлик FileForDetectUPLINK.txt (но он еще пригодится позже, в скрипте)

Скрипт

Весь скрипт я размещу под спойлер, а некоторые его подробности, для понимания как это работает - опишу ниже.

Создадим файл скрипта:
 touch /home/root/backup-all.sh  (путь к файлу может отличаться, а точнее быть вашим :) )
Выставим ограничение в правах к файлу:
 chmod 0700 /home/root/backup-all.sh 
Сделаем файл скрипта исполняемым:
 chmod +x /home/root/backup-all.sh 
Отредактируем файл скрипта:
 nano /home/root/backup-all.sh 


Скрипт для Backup БД MySql и файлов Web-сайта #!/bin/bash

FILE_DETECT=/home/root/YD/FileForDetectUPLINK.txt


if [ -f $FILE_DETECT]; then

        echo "YD - backup successful mount"

else

mount https://webdav.yandex.ru/MyDomains/Backup
        echo "YD was mounted"
fi

SERVER_NAME="ForParents"

TIME=`date +%Y-%b-%d-%H-%M-%S`

### MySql credentials

MYSQL_USER=root
MYSQL_PASSWORD="PasswordDB"

MYSQL_DB1=ForumDB1

MYSQL_DB2=SiteDB1
MYSQL_DB3=ForumDB2

MYSQL_FILE1=/tmp/$SERVER_NAME-mysql-$MYSQL_DB1.$TIME.sql.gz

MYSQL_FILE2=/tmp/$SERVER_NAME-mysql-$MYSQL_DB2.$TIME.sql.gz
MYSQL_FILE3=/tmp/$SERVER_NAME-mysql-$MYSQL_DB3.$TIME.sql.gz


### Archiving filesystem

FS_FILE1=/tmp/$SERVER_NAME-fs-site1.ru.$TIME.tar.gz
FS_FILE2=/tmp/$SERVER_NAME-fs-site2.$TIME.tar.gz
FS_FILE3=/tmp/$SERVER_NAME-fs-site3.$TIME.tar.gz
FS_FILE_SYSTEM=/tmp/$SERVER_NAME-fs-$TIME.tar.gz

tar -czf $FS_FILE_SYSTEM /etc /root

if [ -f $FS_FILE_SYSTEM ]; then
        echo "File system archive completed"
fi
tar -czf $FS_FILE1 /var/www/site1.ru/
if [ -f $FS_FILE1 ]; then
        echo "FS site1.ru  archive completed"
fi
tar -czf $FS_FILE2 /var/www/site2/
if [ -f $FS_FILE2 ]; then
        echo "FS Parents archive completed"
fi
tar -czf $FS_FILE3 /var/www/site3/
if [ -f $FS_FILE3 ]; then
        echo "FS site3 archive completed"
fi

### Archiving databases

mysqldump --user=$MYSQL_USER --password=$MYSQL_PASSWORD $MYSQL_DB1 | gzip > $MYSQL_FILE1
if [ -f $MYSQL_FILE1 ]; then
        echo "db dump Site1 was created"
fi

mysqldump --user=$MYSQL_USER --password=$MYSQL_PASSWORD $MYSQL_DB2 | gzip > $MYSQL_FILE2

if [ -f $MYSQL_FILE2 ]; then
        echo "db dump Parents was  created"
fi

mysqldump --user=$MYSQL_USER --password=$MYSQL_PASSWORD $MYSQL_DB3 | gzip > $MYSQL_FILE3

#mysqldump --user=$MYSQL_USER --password=$MYSQL_PASSWORD --all_databases | gzip > $MYSQL_FILE

if [ -f $MYSQL_FILE3 ]; then

        echo "db dump site3 created"
fi

### Uploading to the cloud


cp -f -R $MYSQL_FILE1 /home/root/YD/DB/

cp -f -R $MYSQL_FILE2 /home/root/YD/DB/
cp -f -R $MYSQL_FILE3 /home/root/YD/DB/

cp -f -R $FS_FILE_SYSTEM /home/root/YD/FS/

cp -f -R $FS_FILE1 /home/root/YD/FS/
cp -f -R $FS_FILE2 /home/root/YD/FS/
cp -f -R $FS_FILE3 /home/root/YD/FS/

echo "All file was copy!"


### Cleanup

unlink $FS_FILE_SYSTEM
unlink $FS_FILE1
unlink $FS_FILE2
unlink $FS_FILE3
unlink $MYSQL_FILE1
unlink $MYSQL_FILE2
unlink $MYSQL_FILE3

find /home/root/YD -type f -mtime +30 -exec rm {} \;




Смысл скрипта безусловно прост, но дополнительно поясню:
С помощью файла, который я разместил на диске - я проверяю наличие смонтированного YD, если это не так - то монтирую YD прямо из скрипта.
Несколько переменных, для удобства и не совсем корректное решение держать логи-пасы в файле, но для меня это не критично, да и на файл ограничение доступа выставлено.
В моем случае - архивируются 3 сайта и 3 базы данных. У вас их может быть больше или меньше. Что подразумевает для каждого сайта - 2 файла. БД и ФС соответственно.
Имеется закомментированная строчка с бекапом всех баз в один файл, на случай, если кто-то не хочет морочиться  с разделением архивов БД.
Далее - простым копированием - мы направляем временные файлы с архивами в нужную нам папку на YD
И подчищаем за собой.
Финальным шагом идет удаление файлов старше 30 дней:
"найти" /home/root/YD -type f (тип файлы) -mtime +30 (старше 30 дней) -exec rm {} \; (передать их в управление RM :) )


Планировщик CRON

Теперь наша задача поставить этот скрипт в планировщик\демон Cron
 crontab -e 
При первом запуске - нам будет предложено выбрать редактор, по умолчанию, если этого еще не сделано.
Затем добавим необходимые записи:
 30 6 * * * /home/root/backup-all.sh 
 30 23 * * * /home/root/backup-all.sh 

В этом случае - скрипт будет исполнятся каждый день в 6:30 утра и 23:30 вечера. Но вы ведь можете и свое время поставить :)

Если необходимо (например для проверки) запустить скрипт прямо здесь и сейчас:
 sh /home/root/backup-all.sh 

В результате - вы увидите в своих папках на ЯД файлы с бекапами данных:

За сим ВСЁ. Прошу прощения у различного рода ГУРУ в ubuntu \ bash'e \ и других не упомянутых в этом предложении профессионалов: я не столь опытен в "ubuntu-подобных" системах, поэтому реализовал как мог : ) А вот если будут дельные подсказки - благодарность вам скажу не только я, но и те, кто это будет использовать и читать :)
Спасибо за внимание!