ESC

Start typing to search across invoices, services, domains, tickets, and more...

Search... Ctrl+K
Linux-сервер

Резервное копирование Linux-сервера: rsync, tar и cron, дамп MySQL/MariaDB и restic в S3

5 шагов 16 мин чтения 1 просмотров 0
Содержание

Отказ диска, случайный rm или атака вымогателя могут уничтожить данные за секунды, поэтому надёжное резервное копирование Linux-сервера обязательно. В статье собраны четыре дополняющих друг друга способа: rsync на другой сервер, архивы tar по расписанию cron, дампы MySQL/MariaDB с ротацией и зашифрованные бэкапы restic в S3-совместимое хранилище, а также проверка восстановления. Команды подходят для Debian/Ubuntu и Rocky Linux/AlmaLinux.

Придерживайтесь правила 3-2-1: три копии данных, на двух типах носителей, одна — вне площадки. Бэкап на том же диске не спасёт при отказе диска или взломе сервера. Если для бэкапов нужен второй сервер или диск большего объёма, уточните конфигурацию у службы поддержки.

Шаг 1: Бэкап на другой сервер с помощью rsync

rsync передаёт только изменения, поэтому идеально подходит для каталогов сайтов и конфигураций. На сервере-хранилище создайте обычного пользователя backup и каталог /backup/web01, а на исходном сервере — отдельный SSH-ключ (см. статью про SSH-ключи). Ключ --delete удаляет на приёмнике файлы, которых нет в источнике, поэтому сначала выполните пробный запуск с -n.

# Install rsync on BOTH servers
apt install -y rsync        # Debian / Ubuntu
dnf install -y rsync        # Rocky Linux / AlmaLinux

# On the source server: dedicated key for backups
ssh-keygen -t ed25519 -f /root/.ssh/backup_key -N ""
ssh-copy-id -i /root/.ssh/backup_key.pub -p 22 [email protected]

# Preview first (-n = dry run), then run for real
rsync -aHn --delete -e "ssh -i /root/.ssh/backup_key -p 22" \
  /etc /var/www [email protected]:/backup/web01/
rsync -aH --delete -e "ssh -i /root/.ssh/backup_key -p 22" \
  /etc /var/www [email protected]:/backup/web01/

Шаг 2: Архивы tar по расписанию cron

rsync делает зеркало: если файл удалён на источнике, при следующей синхронизации он исчезнет и из бэкапа. Поэтому дополнительно создавайте ежедневный архив tar с датой и храните последние семь. Скрипт удаляет старые архивы через find -mtime, а cron запускает его каждую ночь.

cat > /usr/local/bin/backup-files.sh <<'EOF'
#!/bin/bash
set -euo pipefail
DEST=/backup/files
KEEP_DAYS=7
mkdir -p "$DEST"
# tar exit code 1 = "file changed while reading", which is acceptable
tar -czpf "$DEST/files-$(date +%F).tar.gz" /etc /var/www /root || [ $? -eq 1 ]
find "$DEST" -name 'files-*.tar.gz' -mtime +$KEEP_DAYS -delete
EOF
chmod 700 /usr/local/bin/backup-files.sh
/usr/local/bin/backup-files.sh && ls -lh /backup/files

# Schedule: crontab -e
10 3 * * * /usr/local/bin/backup-files.sh >> /var/log/backup.log 2>&1

Шаг 3: Автоматический бэкап MySQL/MariaDB с ротацией

Копирование файлов работающей базы часто даёт повреждённую копию — используйте mysqldump или mariadb-dump. Параметр --single-transaction делает согласованный снимок InnoDB без блокировки таблиц. Скрипт выгружает каждую базу отдельно, сжимает gzip и хранит дампы 14 дней. Учётные данные лежат в /root/.my.cnf с правами 600, чтобы пароль не светился в командной строке и списке процессов.

# Credentials (skip if root can log in to MariaDB/MySQL via unix_socket)
cat > /root/.my.cnf <<'EOF'
[client]
user=root
password=YourDatabaseRootPassword
EOF
chmod 600 /root/.my.cnf

cat > /usr/local/bin/backup-db.sh <<'EOF'
#!/bin/bash
set -euo pipefail
DEST=/backup/mysql
KEEP_DAYS=14
mkdir -p "$DEST"
CLIENT=$(command -v mariadb || command -v mysql)
DUMP=$(command -v mariadb-dump || command -v mysqldump)
for DB in $("$CLIENT" -N -e "SHOW DATABASES" | grep -Ev '^(information_schema|performance_schema|sys)$'); do
  "$DUMP" --single-transaction --routines --triggers --events "$DB" \
    | gzip > "$DEST/$DB-$(date +%F_%H%M).sql.gz"
done
find "$DEST" -name '*.sql.gz' -mtime +$KEEP_DAYS -delete
EOF
chmod 700 /usr/local/bin/backup-db.sh

# Schedule: crontab -e
20 2 * * * /usr/local/bin/backup-db.sh >> /var/log/backup.log 2>&1

Шаг 4: Зашифрованный бэкап restic в S3-совместимое хранилище

restic поддерживает дедупликацию, шифрование и снимки и работает с AWS S3, Cloudflare R2, MinIO и любым S3-совместимым сервисом. Добавьте каталог дампов из шага 3 — так все данные окажутся вне сервера. Команда forget --prune применяет политику хранения по дням, неделям и месяцам и освобождает место.

# Install restic
apt install -y restic                                   # Debian / Ubuntu
dnf install -y epel-release && dnf install -y restic    # Rocky / AlmaLinux

# Repository settings for an S3-compatible bucket
cat > /root/.restic.env <<'EOF'
export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY
export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
export RESTIC_REPOSITORY=s3:https://s3.example.com/my-backup-bucket/web01
export RESTIC_PASSWORD_FILE=/root/.restic.pass
EOF
openssl rand -base64 32 > /root/.restic.pass
chmod 600 /root/.restic.env /root/.restic.pass

. /root/.restic.env
restic init
restic backup /etc /var/www /backup/mysql
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic snapshots

# Schedule: crontab -e
40 3 * * * { . /root/.restic.env && restic backup -q /etc /var/www /backup/mysql && restic forget -q --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune; } >> /var/log/restic.log 2>&1
Без пароля репозитория restic данные восстановить невозможно. Храните /root/.restic.pass и ключи S3 в надёжном месте, например в менеджере паролей, а не только на сервере, который бэкапите.

Шаг 5: Регулярно проверяйте восстановление

Бэкап, из которого ни разу не восстанавливались, — лишь надежда. Хотя бы раз в месяц распакуйте файлы во временный каталог, импортируйте дамп в тестовую базу и сверьте количество строк, выполните restic check. В идеале однажды восстановите всё на новый сервер и засеките время.

# Files: list an archive and extract one directory to a temp folder
tar -tzf /backup/files/files-2026-10-01.tar.gz | head
mkdir -p /tmp/restore
tar -xzf /backup/files/files-2026-10-01.tar.gz -C /tmp/restore etc/nginx

# Database: import into a throw-away database and compare
mysql -e "CREATE DATABASE restore_test"
gunzip -c /backup/mysql/shop-2026-10-01_0220.sql.gz | mysql restore_test
mysql -e "SELECT COUNT(*) FROM restore_test.orders"
mysql -e "DROP DATABASE restore_test"

# restic: verify the repository and restore the latest snapshot
. /root/.restic.env
restic check
restic restore latest --target /tmp/restic-restore --include /etc/nginx

Частые вопросы

Бэкапы заполнили диск — что делать?

Уменьшите KEEP_DAYS, исключите кэш и логи (--exclude в tar) и переносите бэкапы на другой сервер или в объектное хранилище. Советы по очистке — в статье о нехватке места на диске.

Задание cron не выполняется?

Проверьте /var/log/backup.log и journalctl -u cron (на Rocky — crond). В cron очень короткий PATH, поэтому указывайте полные пути и убедитесь, что скрипт исполняемый.

Не замедлит ли дамп большой базы работу сайта?

С InnoDB и --single-transaction таблицы не блокируются, но нагрузка на диск остаётся — запускайте в часы минимального трафика. Для очень больших баз рассмотрите физический горячий бэкап через mariadb-backup или Percona XtraBackup.

Если проблема не решена, создайте тикет — техническая поддержка IMIDC работает 24/7. Укажите IP сервера, версию ОС, выполненные команды и полный текст ошибки, чтобы мы быстрее нашли причину.

Помог ли вам данный ответ?

Похожие руководства