Содержание
Резервное копирование
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
Использование утилиты 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
Restic
https://restic.net/ Перспективная программка.
Документация: https://restic.readthedocs.io/en/latest/010_introduction.html
Urbackup
https://www.urbackup.org/index.html Сервер + клиенты для большинства ОС.
Инфо
Программы для бэкапа на линуксе - Borg, Veeam agent
Rclone - rsync for cloud storage
Статьи
Общие
A Shell Script for a Complete WordPress Backup
Резервное копирование WordPress с помощью mysqldump и tar
Syncing folders to any remote Cloud Storage from a headless Linux server
Backing Up Your WordPress Files
MySQL
date
tar
tar syntax
Using tar to Perform Incremental Dumps
BackupYourSystem
BackupYourSystem/TAR
Создание инкрементального архива с помощью утилиты tar
crontab
Чистка старых файлов
Delete Files Older Than x Days on Linux
Delete files older than X days +
`find -name` pattern that matches multiple patterns
Unix find: multiple file types
Linux find command