Перейти к основному содержанию
Блог

Серверы

Резервные копии и восстановление: от правила 3-2-1 до теста восстановления

Резервная копия полезна, только если из неё можно восстановиться. Правило 3-2-1, шифрование, офлайн-копия, pg_dump/mysqldump и регулярный тест восстановления.

· 10 мин. чтения

Фото: William Hook from Stafford, United Kingdom, CC BY-SA 2.0 · Wikimedia Commons

Во многих командах резервная копия считается «существующей»: в панели включён автоматический бэкап, каждую ночь появляется какой-то архив. Но вопрос нужно ставить иначе: если сегодня сервер полностью выйдет из строя или файлы окажутся зашифрованы, за какое время и до какого состояния вы сможете восстановить систему? Если на этот вопрос нет точного ответа, безопаснее считать, что резервной копии на самом деле нет.

В этой статье разберём, как построить стратегию резервного копирования, правильно делать дамп базы данных, шифровать копии и, главное, регулярно проверять восстановление.

В чём проблема

Типичные ошибки с резервными копиями не технические, а организационные:

  • Копия хранится на том же сервере. Если откажет диск или сервер будет взломан, исчезнут и исходные данные, и копия.
  • Копия всегда подключена. Злоумышленник или программа-шифровальщик (ransomware), попавшие на сервер, видят и подключённый сетевой диск, и облачную папку — и удаляют или шифруют их тоже.
  • Копия не зашифрована. В архиве база данных, файл .env, персональные данные пользователей. Утечка архива равна полной утечке данных.
  • Восстановление ни разу не проверялось. Архив повреждён, дамп записан наполовину или порядок восстановления никто не знает — обычно это выясняется в самый неудобный момент.
  • Копируются только файлы, а база нет (или наоборот). Простое копирование файлов работающей базы часто даёт несогласованное состояние.

Почему это важно для экспертизы

Официальная экспертиза кибербезопасности в основном ищет уязвимости, но рассматриваются и конфигурация сервера, и меры обеспечения информационной безопасности. Находки, связанные с резервными копиями, бывают двух видов:

  1. Раскрытие информации. Оставленные в веб-каталоге файлы вроде backup.zip, db.sql, site.tar.gz можно скачать через браузер. Сканеры проверяют типичные имена, поэтому это обнаруживается быстро.
  2. Восстанавливаемость. Возврат системы в строй после инцидента — часть безопасности. Там, где под угрозой целостность и доступность данных, ожидается задокументированный порядок резервного копирования и восстановления.

Главное правило: резервная копия — это не архив, а возможность восстановления. Непроверенная копия — это предположение.

Правило 3-2-1

Распространённый и простой принцип:

  • 3 копии данных: исходные данные и две резервные;
  • на 2 разных носителях (например, диск сервера и объектное хранилище);
  • 1 копия в другом месте (другой дата-центр, другой провайдер или офлайн-диск в офисе).

Сегодня к нему добавляется ещё одно требование: как минимум одна копия должна быть офлайн или неизменяемой (immutable). Это основная защита от шифровальщиков: даже злоумышленник с полным доступом к серверу не должен иметь возможности удалить эту копию.

На практике неизменяемую копию получают так:

  • функция «object lock» или версионирование со сроком хранения в объектном хранилище;
  • резервный сервер сам «забирает» копию (pull), а основной сервер не имеет права записи на резервный;
  • режим «только добавление» (append-only) — например, так настроенный репозиторий restic или borg;
  • внешний диск, который периодически отключается.

Что нужно копировать

Запишите список заранее, иначе потом обнаружится, что «это тоже было нужно»:

  • база данных (в виде дампа);
  • загруженные пользователями файлы (storage/app, uploads и т. д.);
  • конфигурация: nginx, PHP-FPM, cron, юниты systemd, правила firewall;
  • .env и секреты — отдельно, с надёжным шифрованием;
  • код приложения обычно есть в git, но нужно фиксировать, какая именно версия работает.

Кэш, файлы сессий, каталоги vendor и node_modules копировать не обязательно — они восстанавливаются.

Проверьте сами

Сначала убедитесь, что в веб-каталоге не осталось файлов резервных копий:

find /var/www -type f \( -name "*.sql" -o -name "*.sql.gz" -o -name "*.zip" \
  -o -name "*.tar.gz" -o -name "*.bak" -o -name "*.dump" \) 2>/dev/null

Проверьте и снаружи (только на своём сайте):

for f in backup.zip backup.sql db.sql site.tar.gz dump.sql .env; do
  printf "%s " "$f"; curl -s -o /dev/null -w "%{http_code}\n" "https://example.uz/$f"
done

Ответ 200 означает, что файл открыт. Затем письменно ответьте на вопросы: когда сделана последняя копия, где она хранится, кто может её удалить, когда последний раз из неё восстанавливались.

Правильный дамп базы данных

PostgreSQL

pg_dump делает согласованную копию работающей базы. Пользовательский формат (-Fc) сжат и позволяет выборочное восстановление:

pg_dump -h 127.0.0.1 -U app_backup -Fc -f /backup/app_$(date +%F).dump appdb

Роли и глобальные настройки сохраняются отдельно:

pg_dumpall -h 127.0.0.1 -U postgres --globals-only > /backup/globals_$(date +%F).sql

Не пишите пароль в командной строке — используйте файл ~/.pgpass (chmod 600).

MySQL / MariaDB

Для таблиц InnoDB --single-transaction даёт согласованную копию без блокировки таблиц:

mysqldump --single-transaction --routines --triggers --events \
  -u app_backup appdb | gzip > /backup/appdb_$(date +%F).sql.gz

Учётные данные храните в секции [mysqldump] файла ~/.my.cnf. Для резервного копирования создайте отдельного пользователя только с правами, нужными для чтения и дампа.

Для больших баз дампа может быть недостаточно: восстановление на момент времени (PITR) даёт архивирование WAL в PostgreSQL и binlog в MySQL. Для небольших и средних проектов ежедневный дамп и правильное хранение — обычно достаточная отправная точка.

Шифрование

Резервная копия должна быть зашифрована до того, как покинет сервер. Два распространённых способа:

restic — сам выполняет шифрование, поддерживает дедупликацию и политику хранения:

export RESTIC_REPOSITORY=s3:https://s3.example.com/backups/app
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic backup /backup /var/www/app/storage/app /etc/nginx
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check

age или gpg — шифрование обычного архива открытым ключом. В этом случае на сервере лежит только открытый ключ, а закрытый хранится в другом месте — даже при взломе сервера старые копии расшифровать нельзя:

tar -czf - /backup | age -r age1...publickey > /offsite/app_$(date +%F).tar.gz.age

Не храните ключ или пароль шифрования вместе с копией и не теряйте его: копия без ключа бесполезна. Храните ключ в надёжном месте (менеджер паролей, сейф), известном двум ответственным лицам.

Автоматизация

Ручные копии со временем забываются. Достаточно простого cron или таймера systemd:

# /etc/cron.d/app-backup
30 2 * * * backup /usr/local/bin/app-backup.sh >> /var/log/app-backup.log 2>&1

Если скрипт завершился неудачно, должно прийти уведомление. Самый простой способ — мониторинг «сердцебиения» (heartbeat): скрипт в конце отправляет сигнал, а если сигнал не пришёл, срабатывает оповещение. В проектах на Laravel пакет spatie/laravel-backup в одном месте управляет копированием базы и файлов, очисткой старых копий и уведомлениями.

Тест восстановления

Это самый часто пропускаемый и самый важный шаг. Как минимум раз в месяц:

  1. Подготовьте отдельный тестовый сервер или контейнер (не трогайте рабочую систему).
  2. Скачайте последнюю копию и расшифруйте её.
  3. Восстановите базу:
createdb -h 127.0.0.1 -U postgres restore_test
pg_restore -h 127.0.0.1 -U postgres -d restore_test --no-owner app_2026-10-24.dump
psql -h 127.0.0.1 -U postgres -d restore_test -c "SELECT count(*) FROM users;"

Для MySQL:

gunzip -c appdb_2026-10-24.sql.gz | mysql -u root restore_test
  1. Запустите приложение с этой базой и выполните основные действия: вход, открытие документа, скачивание файла.
  2. Запишите результат: сколько заняло времени, что мешало, какого шага не было в документации.

Из этого теста получаются два важных показателя: RPO — сколько данных вы готовы потерять (при ежедневной копии — до одних суток), и RTO — за какое время вы можете вернуть систему в строй. Согласуйте эти цифры с руководством.

С точки зрения шифровальщиков

При атаке шифровальщика злоумышленник обычно сначала пытается найти и уничтожить резервные копии. Поэтому:

  • у основного сервера не должно быть права удалять копии из хранилища;
  • ключи доступа к хранилищу не должны совпадать с .env основного сервера;
  • как минимум одна копия должна быть неизменяемой или офлайн;
  • при восстановлении выбирайте копию, сделанную до момента инцидента, чтобы не вернуть заражённое состояние, и сначала закройте уязвимость в восстановленной системе.

Смена всех паролей и ключей после восстановления тоже должна быть частью процедуры.

Короткий чек-лист

  • В веб-каталоге нет файлов .sql, .zip, .tar.gz, .bak, и они не открываются снаружи
  • Записан список того, что копируется (база, загруженные файлы, конфигурация, секреты)
  • База дампится согласованно через pg_dump / mysqldump --single-transaction
  • 3-2-1: как минимум одна копия в другом месте, одна неизменяемая или офлайн
  • Копии шифруются до выхода с сервера, ключ хранится отдельно
  • Резервное копирование автоматизировано, о сбоях приходит уведомление
  • Есть политика хранения (ежедневные, еженедельные, ежемесячные)
  • Тест восстановления проводится регулярно, результат записывается
  • RPO и RTO согласованы

Итог

Хорошая система резервного копирования не обязана быть сложной: ежедневный согласованный дамп, шифрование, неизменяемая копия в другом месте и тест восстановления раз в месяц выполнимы и для небольшой команды. В нашем процессе Claude AI агент просматривает настройки сервера, задачи cron и веб-каталог, находит открытые архивы и недостающие шаги, а специалист настраивает порядок резервного копирования и восстановления и проверяет его на практике.

Если хотите узнать, готов ли ваш порядок резервного копирования к экспертизе, оставьте заявку на сканирование. Мы поможем закрыть уязвимости до официальной проверки.