====== Резервное копирование ======
===== 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: мощная утилита для быстрого, гибкого удаленного и локального копирования файлов]]