====== Резервное копирование ====== ===== Docker ===== Для рез. копирования данных на томах создаётся контейнер, который подхватывает все тома целевого контейнера, монтирует каталог с рез. копиями и запускает команду архивации. #!/bin/bash t=$(date +%F) # дата вида 2017-01-01 weekDay=$(date +%u) # номер дня недели sourceDir="/home/user/home" backupDir="/home/user/backup" localDir="$backupDir/local" nasDir="$backupDir/nas" remoteDir="$backupDir/remote" wpDbPass=$(cat $sourceDir/wp-db/wp-db-root.txt) ncDbPass=$(cat $sourceDir/nc-db/nc-db-root.txt) protoprismDbPass=$(cat $sourceDir/photoprism-db/photoprism-db-root.txt) webtreesDbPass=$(cat $sourceDir/webtrees-db/webtrees-db-root.txt) backupPass=$(cat $backupDir/backup-pass.txt) # Выгрузить базы MySQL # https://severalnines.com/database-blog/how-encrypt-your-mysql-mariadb-backups docker exec wp-db mysqldump -uroot -p$wpDbPass -A |gzip |openssl enc -aes-256-cbc -pbkdf2 -k $backupPass > $localDir/$t-wp.sql.gz docker exec nc-db mysqldump -uroot -p$ncDbPass -A |gzip |openssl enc -aes-256-cbc -pbkdf2 -k $backupPass > $localDir/$t-nc.sql.gz docker exec photoprism-db mysqldump -uroot -p$protoprismDbPass -A |gzip |openssl enc -aes-256-cbc -pbkdf2 -k $backupPass > $localDir/$t-photoprism.sql.gz docker exec webtrees-db mysqldump -uroot -p$webtreesDbPass -A |gzip |openssl enc -aes-256-cbc -pbkdf2 -k $backupPass > $localDir/$t-webtrees.sql.gz # Файлы проекта # https://www.tecmint.com/encrypt-decrypt-files-tar-openssl-linux/ tar --create --preserve-permissions --gzip $sourceDir | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-project.tar.gz -pass pass:$backupPass # Файлы контейнеров if [ $weekDay -eq 2 ] then # Удалить старые файлы старше 2 недель find $localDir -name '*.gz*' -mtime +14 -exec rm -f {} \; # Full backup docker run --rm --volumes-from wp -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/wp-0.snar --level=0 /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-wp-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from wiki -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/wiki-0.snar --level=0 /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-wiki-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from nc -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/nc-0.snar --level=0 /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-nc-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from photoprism -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/photoprism-0.snar --level=0 /photoprism | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-photoprism-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from webtrees -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/webtrees-0.snar --level=0 /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-webtrees-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from bepasty -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/bepasty-0.snar --level=0 /srv/bepasty | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-bepasty-full.tar.gz -pass pass:$backupPass docker run --rm --volumes-from phpsysinfo -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/phpsysinfo-0.snar --level=0 /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-phpsysinfo-full.tar.gz -pass pass:$backupPass else # Copy snars for diff backup for f in $backupDir/*-0.snar; do cp "$f" "${f/-0.snar/-1.snar}"; done # Differential backup docker run --rm --volumes-from wp -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/wp-1.snar /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-wp.tar.gz -pass pass:$backupPass docker run --rm --volumes-from wiki -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/wiki-1.snar /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-wiki.tar.gz -pass pass:$backupPass docker run --rm --volumes-from nc -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/nc-1.snar /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-nc.tar.gz -pass pass:$backupPass docker run --rm --volumes-from photoprism -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/photoprism-1.snar /photoprism | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-photoprism.tar.gz -pass pass:$backupPass docker run --rm --volumes-from webtrees -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/webtrees-1.snar /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-webtrees.tar.gz -pass pass:$backupPass docker run --rm --volumes-from bepasty -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/bepasty-1.snar /srv/bepasty | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-bepasty.tar.gz -pass pass:$backupPass docker run --rm --volumes-from phpsysinfo -v $backupDir:/backup ubuntu \ tar --create --preserve-permissions --gzip --listed-incremental=/backup/phpsysinfo-1.snar /var/www/html | \ openssl enc -e -aes-256-cbc -pbkdf2 -out $localDir/$t-phpsysinfo.tar.gz -pass pass:$backupPass fi # Разбивка на файлы по 2 ГБ, созданных за последние сутки # https://www.tecmint.com/split-large-tar-into-multiple-files-of-certain-size/ bigFiles=($(find $localDir -type f -size +2G -mtime -1)) for f in ${bigFiles[*]}; do split -b 2G "$f" "$localDir/$(basename "$f").part" done # Выгрузка на NAS mount $nasDir # https://linuxize.com/post/bash-check-if-file-exists/ if [ -f "$nasDir/server-available" ] then rsync --delete --recursive --size-only --include="*.gz" --exclude="*" $localDir/ $nasDir fi umount $nasDir # Выгрузка на удалённый сервер (WebDAV) mount $remoteDir if [ -f "$remoteDir/server-available" ] then rsync --delete --recursive --size-only --max-size=2G --exclude="lost+found" --exclude="server-available" $localDir/ $remoteDir fi # sleep 10m umount $remoteDir https://severalnines.com/database-blog/how-encrypt-your-mysql-mariadb-backups\\ https://www.tecmint.com/encrypt-decrypt-files-tar-openssl-linux\\ https://docs.docker.com/storage/volumes/#backup-restore-or-migrate-data-volumes ===== Монолит ===== - Делать резервные копии двух баз MySQL - Делать резервные копии корневой папки веб-сервера вместе с содержимым симлинков внутри неё - Сжимать бэкап для экономии места - Шифровать его, чтобы бэкап можно было класть на публичные сервисы - Синхронизировать результат с удалёнными хранилищами, в данном случае по webdav на 4shared. - Делать полную копию файлов каждое воскресенье, прочие дни - дифференциальную копию - Удалять старые резервные копии старше двух недель ==== Создать каталоги ==== # Для резервных копий (на sdcard) mkdir /media/sdcard/backup # Для зашифрованных резервных копий mkdir /media/sdcard/backup/encrypted # Для монтирования 4shared WebDAV mkdir /media/webdav/4shared ==== Установить и настроить программу для монтирования webdav ==== # Установить компонент webdav sudo apt-get install davfs2 -y # На вопрос монтирования каталогов от непривилегированных пользователей ответить "да". # Чтобы изменить это позже: dpkg-reconfigure davfs2 # Включить пользователя в группу davfs2 (если он не root) sudo usermod -aG davfs2 $USER # Прописать файл адреса, логина и пароля для подключения, права на файл mkdir $HOME/.davfs2 touch $HOME/.davfs2/secrets chmod 600 $HOME/.davfs2/secrets nano $HOME/.davfs2/secrets # для рута - файл /etc/davfs2/secrets # Вставить в конец файла строки примерно следующего вида # (в данном случае путь указывает сразу в папку на удалённом сервере): https://nextcloud.domain.ru/remote.php/webdav/backup login password https://webdav.4shared.com/backup/orangepipc2 login password https://webdav.yandex.ru/backup login password # Для непривилегированного пользователя необходимо прописать строку в /etc/fstab, # иначе монтироваться вручную не будет. В данном случае, noauto - не монтировать при запуске системы echo "# davfs" >> /etc/fstab echo "https://webdav.4shared.com/backup/orangepipc2 /home/user/backup/remote davfs user,rw,noauto 0 0" >> /etc/fstab # Убрать предупреждение при монтировании /sbin/mount.davfs: warning: the server does not support locks # Раскомментировать и исправить параметр sudo sed -i '/use_locks/c use_locks 0' /etc/davfs2/davfs2.conf # После этого, можно будет монтировать удалённый каталог командой mount $HOME/backup/remote # и размонтировать umount $HOME/backup/remote [[http://help.ubuntu.ru/wiki/davfs2|Использование утилиты davfs2 для монтирования сетевых облачных хранилищ по протоколу WebDAV]] ==== Скрипт ==== #!/bin/bash BACKUP_TIME=$(date +"%F") # дата вида 2017-01-01 DOW=$(date +%u) # Day of week SOURCE_DIR="/var/www/html" BACKUP_DIR="/media/usb8gb/backup" ENCRYPTED_DIR="$BACKUP_DIR/encrypted" WEBDAV_SITE_4SHARED="https://webdav.4shared.com/backup/orangepipc2" # 4shared WEBDAV_DIR_4SHARED="/media/4shared" FULL="$BACKUP_TIME-files-full.tar.gz" DIFF="$BACKUP_TIME-files-diff.tar.gz" FULL_ENCRYPTED="$FULL.aes" # Зашифрованный архив с файлами веб-сервера DIFF_ENCRYPTED="$DIFF.aes" PASS="pass" # Пароль для шифрования # Параметры MySQL DB_USER="mysqluser" DB_PASS="mysqlpass" WP_DB="wordpress" CLOUD_DB="cloud" WP_DB_FILE="$BACKUP_TIME-$WP_DB.sql" CLOUD_DB_FILE="$BACKUP_TIME-$CLOUD_DB.sql" WP_DB_FILE_COMPRESSED="$WP_DB_FILE.gz" CLOUD_DB_FILE_COMPRESSED="$CLOUD_DB_FILE.gz" WP_DB_FILE_ENCRYPTED="$WP_DB_FILE_COMPRESSED.aes" CLOUD_DB_FILE_ENCRYPTED="$CLOUD_DB_FILE_COMPRESSED.aes" # Выгрузить базы MySQL mysqldump --add-drop-table -u$DB_USER -p$DB_PASS $WP_DB > $BACKUP_DIR/$WP_DB_FILE mysqldump --add-drop-table -u$DB_USER -p$DB_PASS $CLOUD_DB > $BACKUP_DIR/$CLOUD_DB_FILE gzip $BACKUP_DIR/*.sql # Сжать базы MySQL openssl enc -aes-256-cbc -pbkdf2 -in $BACKUP_DIR/$WP_DB_FILE_COMPRESSED -out $ENCRYPTED_DIR/$WP_DB_FILE_ENCRYPTED -pass pass:$PASS openssl enc -aes-256-cbc -pbkdf2 -in $BACKUP_DIR/$CLOUD_DB_FILE_COMPRESSED -out $ENCRYPTED_DIR/$CLOUD_DB_FILE_ENCRYPTED -pass pass:$PASS if [ $DOW -eq 7 ] then # Удалить старые файлы старше 2 недель find $ENCRYPTED_DIR -name '*.aes' -mtime +14 -exec rm -f {} \; # Резервное копирование (полный) tar --create --preserve-permissions --dereference --gzip --listed-incremental="$BACKUP_DIR/level-0.snar" --level=0 --file=$BACKUP_DIR/$FULL $SOURCE_DIR openssl enc -aes-256-cbc -pbkdf2 -in $BACKUP_DIR/$FULL -out $ENCRYPTED_DIR/$FULL_ENCRYPTED -pass pass:$PASS else # Резервное копирование (дифференциальное) cp "$BACKUP_DIR/level-0.snar" "$BACKUP_DIR/level-1.snar" tar --create --preserve-permissions --dereference --gzip --listed-incremental="$BACKUP_DIR/level-1.snar" --file=$BACKUP_DIR/$DIFF $SOURCE_DIR openssl enc -aes-256-cbc -pbkdf2 -in $BACKUP_DIR/$DIFF -out $ENCRYPTED_DIR/$DIFF_ENCRYPTED -pass pass:$PASS fi # Удалить исходные незашифрованные архивы find $BACKUP_DIR -name '*.gz' -exec rm -f {} \; # Закачать полученные зашифрованные архивы на удалённые серверы # Смонтировать удалённые каталоги webdav mount -t davfs $WEBDAV_SITE_4SHARED $WEBDAV_DIR_4SHARED # Синхронизировать локальные каталоги с удалёнными (только зашифрованные файлы) rsync --delete --recursive --size-only --exclude="lost+found" $ENCRYPTED_DIR/ $WEBDAV_DIR_4SHARED # Иногда бывало, что после окончания работы rsync # данные реально не успевают закачаться на серверы, по этой причине # после отмонтирования разделов WebDAV эти данные попадают в /var/cache, # что забивает системный раздел. По этой причине, в скрипт вставлена пауза. # sleep 30m # Размонтировать удалённые каталоги WebDAV umount -t davfs $WEBDAV_DIR_4SHARED Создать файл backup.sh, вставить туда код и отредактировать пути, логины и пароли. Сделать файлы скриптов запускаемыми: chmod +x backup.sh Настроить планировщик: crontab -e # Cleanup davfs cache 0 8 * * 7 root rm -rf /var/cache/davfs2/* # Backup 0 3 * * * /root/backup.sh === Проблемы === В один прекрасный день WebDAV перестал синхронизировать, на попытку смонтировать каталог выдаёт:\\ /sbin/mount.davfs: found PID file /var/run/mount.davfs/media-webdav.pid. Either /media/webdav is used by another process, or another mount process ended irregular # Решение: rm /var/run/mount.davfs/media-webdav.pid ==== Полезные команды ==== === Вывести список БД === mysql -u root -p111111 show databases; +--------------------+ | Database | +--------------------+ | information_schema | | cloud | | mysql | | performance_schema | | sys | | wordpress | +--------------------+ === Copy folder with following symlinks === cp -L -r /var/www/html ~/backup (‘-L’ ,‘--dereference’ - Follow symbolic links when copying from them. With this option, cp cannot create a symbolic link. For example, a symlink (to regular file) in the source tree will be copied to a regular file in the destination tree.) === Скопировать папку рекурсивно с сохранением всех свойств файлов === # папка backup создастся на usb8gb cp -rp /media/sdcard/backup /media/usb8gb === Посмотреть размеры вложенных каталогов и вывести общий размер === du -sch /media/sdcard/* ===== Borg ===== Latest release: https://github.com/borgbackup/borg/releases/latest\\ Installation: https://borgbackup.readthedocs.io/en/stable/installation.html\\ Quick start: https://borgbackup.readthedocs.io/en/stable/quickstart.html borg init --encryption=none /path/to/repo # create unencrypted repo (not recommended) borg create /path/to/repo::Monday ~/src ~/Documents # "Monday" is a name https://habr.com/ru/company/flant/blog/420055/ ===== Restic ===== https://restic.net/ Перспективная программка. Документация: https://restic.readthedocs.io/en/latest/010_introduction.html [[https://www.youtube.com/watch?v=OKXhrpLbGkc&list=PLFxkuUNT-SE0Hy2X00jgBBTBg0Z8cFahy|DeAndre Queary - Restic Complete Guide]] ===== Urbackup ===== https://www.urbackup.org/index.html Сервер + клиенты для большинства ОС. https://christitus.com/urbackup/ ===== Инфо ===== Программы для бэкапа на линуксе - [[https://www.borgbackup.org/|Borg]], [[https://www.veeam.com/ru/windows-linux-availability-agents.html|Veeam agent]] [[https://rclone.org/|Rclone]] - rsync for cloud storage ===== Статьи ===== ==== Общие ==== [[http://theme.fm/a-shell-script-for-a-complete-wordpress-backup/|A Shell Script for a Complete WordPress Backup]]\\ [[https://wpmag.ru/2014/rezervnoe-kopirovanie-wordpress-mysqldump-tar/|Резервное копирование WordPress с помощью mysqldump и tar]]\\ [[https://blog.storagemadeeasy.com/syncing-folders-to-any-remote-cloud-storage-from-a-headless-linux-server/|Syncing folders to any remote Cloud Storage from a headless Linux server]]\\ [[https://codex.wordpress.org/Backing_Up_Your_WordPress_Files|Backing Up Your WordPress Files]] ==== MySQL ==== [[https://codex.wordpress.org/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%BD%D0%BE%D0%B9_%D0%BA%D0%BE%D0%BF%D0%B8%D0%B8_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85|Создание резервной копии БД]] ==== date ==== [[http://www.computerhope.com/unix/udate.htm|Linux and Unix date command]] ==== tar ==== [[http://www.computerhope.com/unix/utar.htm|tar syntax]]\\ [[http://www.gnu.org/software/tar/manual/html_node/Incremental-Dumps.html|Using tar to Perform Incremental Dumps]]\\ [[https://help.ubuntu.com/community/BackupYourSystem|BackupYourSystem]]\\ [[https://help.ubuntu.com/community/BackupYourSystem/TAR|BackupYourSystem/TAR]]\\ [[https://www.opennet.ru/tips/2341_tar_backup_archive.shtml|Создание инкрементального архива с помощью утилиты tar]] ==== crontab ==== [[http://www.computerhope.com/unix/ucrontab.htm|Linux and Unix crontab command]] ==== Чистка старых файлов ==== [[https://www.howtogeek.com/howto/ubuntu/delete-files-older-than-x-days-on-linux/|Delete Files Older Than x Days on Linux]]\\ [[http://unix.stackexchange.com/questions/194863/delete-files-older-than-x-days|Delete files older than X days +]]\\ [[http://stackoverflow.com/questions/1133698/find-name-pattern-that-matches-multiple-patterns|`find -name` pattern that matches multiple patterns]]\\ [[http://stackoverflow.com/questions/7190565/unix-find-multiple-file-types|Unix find: multiple file types]]\\ [[http://www.binarytides.com/linux-find-command-examples/|Linux find command]] ==== rsync ==== [[http://www.tecmint.com/rsync-local-remote-file-synchronization-commands/|10 Practical Examples of Rsync Command in Linux]]\\ [[https://ubuntuforums.org/showthread.php?t=763833&s=2244299828c5d464a830d9b892da5d4a&p=8546521#post8546521|Re: rsync - including only certain extensions]]\\ [[http://www.computerhope.com/unix/rsync.htm|Linux and Unix rsync command]]\\ [[https://habrahabr.ru/sandbox/37102/|Rsync: мощная утилита для быстрого, гибкого удаленного и локального копирования файлов]]