Коротко. Полный бэкап сайта — это файлы приложения и загрузки пользователей, согласованный дамп базы данных, конфиги веб-сервера и PHP, cron и таймеры, TLS-сертификаты и переменные окружения. Хранить нужно минимум три копии на двух разных площадках, одну — вне сервера. Частоту задают RPO и RTO. Бэкап, который ни разу не разворачивали на тестовом домене, бэкапом не считается.
Что входит в полный бэкап сайта и почему «архив public_html» — это не бэкап
Резервная копия должна позволять поднять работающий сайт на пустом сервере, а не только вернуть удалённую картинку. Если после аварии у вас есть только public_html.tar.gz, восстановление превращается в многочасовую реконструкцию по памяти: какая была версия PHP, какие расширения включены, что было в rewrite-правилах, какие задания висели в crontab, где лежал приватный ключ сертификата.
Минимальный состав полного бэкапа:
- Код приложения — ядро CMS, темы, модули, кастомный код. Если код лежит в Git, бэкап кода — это репозиторий плюс зафиксированный коммит боевой версии.
- Пользовательские загрузки —
wp-content/uploads,/uploadу Битрикса, каталоги медиа и документов. Обычно это самая большая и невосстановимая часть: код можно переустановить, фотографии товаров — нет. - База данных — согласованный дамп, а не копия файлов на живую.
- Конфигурация веб-сервера и PHP —
/etc/nginx, виртуальные хосты Apache,/etc/php/*/fpm/pool.d, лимиты, таймауты, правила кэширования. - Планировщик — пользовательские crontab, файлы в
/etc/cron.d, юниты и таймеры systemd. Без них сайт запустится, но перестанут уходить письма, обновляться фиды и чиститься кэш. - Сертификаты и ключи —
/etc/letsencryptцеликом (включаяaccountsиrenewal), приватные ключи, DH-параметры. - Переменные окружения и секреты —
.env, настройки подключения к БД, ключи платёжных шлюзов, токены API. Обычно их нет в репозитории, а без них приложение не стартует. - Почта и служебные данные — конфиг релея, ящики, если они на этом же сервере; списки пакетов и версии, чтобы воспроизвести окружение.
Никогда не кладите архив бэкапа внутрь веб-корня. Файлы видаbackup.zip,dump.sql,site_2026.tar.gzв корне сайта индексируются, перебираются ботами по словарю и регулярно утекают целиком — вместе со всей базой пользователей. Каталог бэкапов должен быть внеDocumentRootи закрыт правами доступа.

Правило 3-2-1: почему копия на том же сервере не считается
Классическое правило звучит так: три копии данных, на двух разных типах носителей или площадок, одна из них — за пределами основной инфраструктуры. Боевые данные считаются первой копией.
Копия, лежащая на том же сервере в соседнем каталоге, не защищает ни от одного из реальных сценариев потери:
- отказ или деградация диска — пропадают и данные, и архив;
- ошибочная команда удаления или неудачный деплой, который вычищает каталог целиком;
- компрометация сервера: программа-вымогатель первым делом ищет и шифрует локальные каталоги с бэкапами;
- потеря доступа к аккаунту у провайдера — сервер и его снапшоты недоступны одновременно;
- ошибка в биллинге и остановка виртуальной машины вместе с дисками.
Расширенная версия правила добавляет ещё два условия: одна копия должна быть неизменяемой или офлайн, и все проверки восстановления должны проходить с нулём ошибок. На практике «неизменяемость» реализуется ключом доступа к объектному хранилищу, у которого есть права на запись и чтение, но нет права на удаление. Удаление старых копий (prune) запускается отдельным заданием с другим ключом и, желательно, с другой машины.
Проверка на честность. Представьте, что боевой сервер полностью недоступен прямо сейчас: провайдер заблокировал аккаунт, доступа к панели нет. Сможете ли вы получить бэкап? Если ответ «нет», правило 3-2-1 у вас не выполнено.
RPO и RTO простыми словами: как из них выводится частота бэкапа
RPO (recovery point objective) — сколько данных вы готовы потерять. Это расстояние между последней резервной копией и моментом аварии. Если бэкап снимается раз в сутки в 03:20, а сайт упал в 18:00, вы потеряли почти 15 часов работы: заказы, комментарии, загруженные файлы.
RTO (recovery time objective) — сколько времени бизнес готов лежать. Сюда входит всё: обнаружение аварии, поиск последней рабочей копии, скачивание архива, разворачивание окружения, импорт базы, переключение DNS и прогрев кэша.
Частота бэкапов выводится из RPO напрямую: интервал между копиями не должен превышать допустимую потерю. RTO определяет технологию: если нужен возврат за 30 минут, скачивание 200-гигабайтного архива по узкому каналу не подходит — нужен либо горячий резерв, либо хранилище рядом с сервером плюс отдельная удалённая копия.
| Тип проекта | Разумный RPO | Разумный RTO | Схема |
|---|---|---|---|
| Сайт-визитка, лендинг | 24 часа | 4–8 часов | Ежедневный полный бэкап файлов и БД |
| Корпоративный сайт с формами | 6–12 часов | 2–4 часа | Файлы раз в сутки, БД каждые 6 часов |
| Блог, СМИ, UGC | 1–3 часа | 1–2 часа | Инкрементальный бэкап файлов, частый дамп БД |
| Интернет-магазин с онлайн-оплатой | 5–15 минут | до 1 часа | Полный дамп плюс непрерывный архив журналов транзакций |
Значения в таблице — ориентир для разговора с владельцем сайта, а не норматив. Правильный порядок действий обратный: сначала бизнес называет допустимую потерю и допустимый простой, потом под них подбирается схема и бюджет.
Типы бэкапов: полный, инкрементальный, дифференциальный и снапшоты
Полный — копируется всё целиком. Просто восстанавливать (нужен ровно один архив), дорого хранить и долго снимать.
Инкрементальный — копируются изменения относительно предыдущей копии любого типа. Экономно по объёму и времени, но для восстановления нужна вся цепочка: полный бэкап плюс все инкременты по порядку. Обрыв в середине цепочки делает бесполезным всё, что после него.
Дифференциальный — копируются изменения относительно последнего полного бэкапа. Занимает больше места, чем инкрементальный, но для восстановления нужны только два элемента: полный плюс последний дифференциальный.
Современные дедуплицирующие инструменты (restic, borg) стирают эту границу: физически они пишут только новые блоки, но логически каждый снимок выглядит как полный и восстанавливается независимо. Для сайтов это почти всегда лучший компромисс.
Снапшот диска у провайдера — не бэкап
Снапшот виртуального диска удобен: он снимается за секунды и позволяет откатить машину целиком. Но у него три принципиальных ограничения.
- Он живёт в той же инфраструктуре и в том же аккаунте, что и сервер. Потеря доступа к аккаунту, блокировка, ошибка на стороне площадки — и снапшоты недоступны вместе с машиной.
- Он не гарантирует согласованность базы данных. Снапшот делается на уровне блочного устройства и фиксирует файлы СУБД в произвольный момент — возможно, посередине записи страницы. Восстановленная база может подняться только после аварийного восстановления журнала, а может не подняться вовсе.
- Из него сложно достать один файл. Чтобы вытащить случайно удалённую страницу, приходится разворачивать всю машину.
Снапшот — отличная точка отката перед обновлением CMS или миграцией. Как единственная защита данных он не годится. Подробнее о том, где снапшот действительно уместен, — в чек-листе переноса сайта.

Согласованный бэкап базы данных: mysqldump и его альтернативы
Самая частая ошибка — копировать каталог данных СУБД (/var/lib/mysql) обычным rsync или tar на работающем сервере. Пока идёт копирование, движок продолжает писать: часть страниц попадает в архив в старом состоянии, часть в новом, журнал не соответствует табличным файлам. На выходе получается архив, который либо не поднимается вообще, либо поднимается с потерянными строками — и вы узнаёте об этом в момент аварии.
Для InnoDB корректный логический дамп снимается одной транзакцией: сервер отдаёт согласованный снимок на момент старта дампа, не блокируя запись.
mysqldump --defaults-extra-file=/root/.my.cnf --single-transaction --quick --routines --events --triggers --hex-blob --no-tablespaces --default-character-set=utf8mb4 --databases sitedb | gzip -9 > /var/backups/site/db/sitedb-$(date +%F-%H%M).sql.gz
# коды возврата всей цепочки: mysqldump и gzip по отдельности
echo "${PIPESTATUS[@]}"
# проверка целостности логического дампа
zcat /var/backups/site/db/sitedb-*.sql.gz | tail -3 | grep -q 'Dump completed' || echo 'BROKEN DUMP'
Что делают ключевые флаги:
--single-transaction— согласованный снимок для InnoDB без блокировки таблиц. Для MyISAM не работает: там придётся использовать--lock-all-tablesи мириться с паузой записи.--quick— построчная выгрузка вместо буферизации всей таблицы в памяти. Обязателен для больших таблиц.--routines --events --triggers— процедуры, события планировщика и триггеры. Без них база восстановится «пустой» с точки зрения логики.--hex-blob— двоичные поля в шестнадцатеричном виде, чтобы не ломались при переносе между кодировками.--no-tablespaces— нужен на современных версиях MySQL, если у пользователя дампа нет привилегии PROCESS.--defaults-extra-file— пароль читается из файла с правами 600, а не из командной строки, где его видно в списке процессов.
Важно. Режим--single-transactionдаёт согласованность только при отсутствии DDL. Если во время дампа выполняетсяALTER TABLEили обновление модуля CMS меняет схему, снимок перестаёт быть согласованным молча — без ошибки. Планируйте бэкап на окно, когда не идут обновления, и не запускайте деплой параллельно с ним.
Для PostgreSQL логический аналог — pg_dump -Fc (сжатый пользовательский формат, восстанавливается через pg_restore с параллелизмом). Для баз в десятки гигабайт логический дамп восстанавливается слишком долго: там переходят на физический бэкап (для MySQL — семейство утилит горячего копирования, для PostgreSQL — pg_basebackup плюс архивация журналов WAL). Физический бэкап быстрее восстанавливается и позволяет откатиться на произвольный момент времени, но привязан к версии и платформе СУБД. Разумный компромисс для среднего сайта: ежедневный логический дамп плюс, если RPO меньше часа, непрерывная архивация журналов.
Шифрование бэкапов и хранение ключа отдельно
Дамп базы сайта — это персональные данные в чистом виде: имена, телефоны, адреса доставки, хеши паролей, история заказов, содержимое обращений. Утечка одного архива равна утечке всей клиентской базы за всё время работы. Поэтому бэкап шифруется до отправки во внешнее хранилище, на стороне сервера.
Инструменты restic и borg делают это по умолчанию: репозиторий шифруется целиком, хранилище видит только зашифрованные блоки. Если вы собираете архивы вручную, шифруйте их симметрично или на открытый ключ перед загрузкой.
Где хранить ключ
Ключ или парольная фраза не должны лежать только на том сервере, который вы бэкапите. Иначе схема вырождается: компрометация сервера означает и доступ к архивам, а потеря сервера означает потерю ключа и невозможность расшифровать копии.
- рабочая копия ключа — на сервере, файл с правами 600 и владельцем root;
- вторая копия — в менеджере секретов или парольном хранилище команды;
- третья — офлайн: распечатка или зашифрованный носитель в сейфе.
Ключ, лежащий рядом с зашифрованным архивом, равен отсутствию шифрования. Это относится и к переменным окружения в том же контейнере, и к паролю, прописанному в скрипте, который сам попадает в бэкап.
Юридическая сторона
Бэкап с персональными данными — это по-прежнему обработка персональных данных. Из этого следуют практические требования: у резервных копий должен быть определённый и документированный срок хранения, они должны попадать в перечень мест хранения ПДн, а запрос на удаление данных должен либо затрагивать бэкапы, либо покрываться политикой ротации с внятным сроком. Бесконечное хранение «на всякий случай» создаёт риск и не даёт пользы. Что ещё проверить в этой части — в проверке сайта на соответствие 152-ФЗ.
Рабочая схема: скрипт, таймер, объектное хранилище и retention
Ниже — каркас скрипта, который делает три вещи, которых почти всегда не хватает самописным бэкапам: останавливается на первой ошибке, проверяет правдоподобность результата и сообщает о себе наружу.
#!/bin/bash
# /usr/local/sbin/site-backup.sh
set -Eeuo pipefail
TS=$(date +%F-%H%M)
WORK=/var/backups/site
DUMP="$WORK/db/sitedb-$TS.sql.gz"
MIN_BYTES=$((20 * 1024 * 1024)) # порог «подозрительно маленького» дампа
ALERT_URL="https://alerts.example.com/hook"
PING_URL="https://monitor.example.com/ping/site-backup"
notify() {
logger -t site-backup "$1"
curl -fsS -m 10 --data-urlencode "text=site-backup: $1" "$ALERT_URL" >/dev/null || true
}
trap 'notify "FAILED at line $LINENO"' ERR
install -d -m 700 "$WORK/db"
mysqldump --defaults-extra-file=/root/.my.cnf --single-transaction --quick --routines --events --triggers --hex-blob --no-tablespaces --databases sitedb | gzip -9 > "$DUMP"
[ "${PIPESTATUS[0]}" -eq 0 ] || { notify "mysqldump failed"; exit 1; }
SIZE=$(stat -c %s "$DUMP")
if [ "$SIZE" -lt "$MIN_BYTES" ]; then
notify "dump suspiciously small: $SIZE bytes"
exit 1
fi
export RESTIC_REPOSITORY="s3:https://s3.example.com/backups-site"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
restic backup --tag daily --one-file-system "$WORK/db" /var/www/site /etc/nginx /etc/php /etc/letsencrypt /etc/cron.d
restic forget --tag daily --prune --keep-daily 14 --keep-weekly 8 --keep-monthly 12
curl -fsS -m 10 "$PING_URL" >/dev/null || true
notify "OK, dump $SIZE bytes"
Ключевые детали: set -Eeuo pipefail плюс trap ... ERR превращают любую необработанную ошибку в уведомление, а не в тихий пропуск ночи. Проверка минимального размера ловит самый коварный класс отказов — когда mysqldump отработал с нулевым кодом, но выгрузил пустую базу из-за смены пароля или прав. Финальный curl — это heartbeat: внешняя система ждёт этот сигнал и поднимает тревогу, если он не пришёл.
Запуск по расписанию — обычной строкой cron. Обратите внимание на перенаправление вывода: без него ошибки уходят в почту root, которую никто не читает.
# /etc/cron.d/site-backup
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
20 3 * * * root /usr/local/sbin/site-backup.sh >> /var/log/site-backup.log 2>&1
Если сервер под systemd, надёжнее оформить задание парой юнитов. В site-backup.service достаточно Type=oneshot и ExecStart, а в site-backup.timer расписание задаётся директивой OnCalendar со значением вида *-*-* 03:20:00. Полезно добавить RandomizedDelaySec=900, чтобы десяток серверов не начинал выгрузку в одну секунду, и Persistent=true, чтобы пропущенный из-за выключения запуск выполнился после старта. Преимущество таймера перед cron — журналирование в journald, статус последнего запуска и корректная обработка перекрывающихся выполнений.
# /etc/systemd/system/site-backup.service
[Unit]
Description=Site backup
After=network-online.target mysql.service
[Service]
Type=oneshot
Nice=10
IOSchedulingClass=idle
ExecStart=/usr/local/sbin/site-backup.sh
Политика хранения (retention) — компромисс между стоимостью и глубиной. Рабочая отправная точка для сайта: 14 ежедневных, 8 еженедельных, 12 ежемесячных копий. Ежедневные закрывают бытовые ошибки, еженедельные — замеченные с опозданием, ежемесячные — заражения и повреждения данных, которые обнаружились через месяцы.

Что чем копировать: справочная таблица
| Объект | Чем копировать | Частота | Куда | Как проверять |
|---|---|---|---|---|
| Код приложения | Git-репозиторий, restic/borg по каталогу | При каждом релизе + ежедневно | Внешний репозиторий + объектное хранилище | Развернуть тег и сравнить контрольные суммы файлов |
| Загрузки пользователей (медиа) | rsync, restic, borg | Ежедневно, при активной загрузке — чаще | Объектное хранилище + вторая площадка | Сверить число файлов и суммарный объём с боевым |
| База данных | mysqldump / pg_dump; для больших — физический бэкап | От раза в сутки до непрерывной архивации журналов | Локально на короткий срок, затем внешнее хранилище | Импорт в тестовую базу, сверка числа записей ключевых таблиц |
| Конфиги nginx/Apache и PHP | Git-репозиторий конфигов или restic по /etc | При каждом изменении + еженедельно | Репозиторий + объектное хранилище | nginx -t и php-fpm -t на восстановленной копии |
| cron и systemd-таймеры | Выгрузка crontab -l, копия /etc/cron.d и юнитов | При изменении + еженедельно | Вместе с конфигами | Сверить список заданий с боевым сервером |
| Сертификаты и приватные ключи | Архив /etc/letsencrypt, обязательно зашифрованный | Ежедневно (обновление автоматическое) | Только зашифрованное хранилище | Проверить срок действия и соответствие ключа сертификату |
| Переменные окружения и секреты | Зашифрованный файл или менеджер секретов | При каждом изменении | Менеджер секретов + офлайн-копия | Тестовый запуск приложения на восстановленной копии |
| Почта на сервере | Архив каталога ящиков + конфиг релея | Ежедневно | Внешнее хранилище | Открыть восстановленный ящик, отправить тестовое письмо |
| DNS-зона | Экспорт зоны из панели DNS-провайдера | При изменении | Репозиторий конфигов | Сверить записи с фактическим ответом резолверов |
Бэкапы средствами CMS: WordPress и Битрикс
Штатные и плагинные решения удобны тем, что не требуют доступа к серверу. Но они работают внутри PHP-процесса и наследуют все его ограничения.
WordPress
Плагины резервного копирования собирают архив и дамп силами самого PHP. Типичные проблемы: упирание в max_execution_time и memory_limit на больших uploads; частичный архив без сообщения об ошибке; складывание архивов в wp-content, откуда их скачивают по перебираемому имени; и главное — если сайт лежит, админка недоступна, а вместе с ней и механизм восстановления.
Более предсказуемый вариант — WP-CLI на сервере: wp db export для дампа и wp core verify-checksums для контроля целостности ядра перед снятием копии. Но и это лишь дополнение к серверному бэкапу.
1С-Битрикс
Штатный модуль резервного копирования умеет разбивать архив на части и выполнять шаги по расписанию, но на крупных проектах регулярно упирается в предельный размер архива, время шага и место на диске. Каталог /bitrix/backup/ лежит внутри веб-корня, поэтому доступ к нему обязательно должен быть закрыт на уровне веб-сервера. Отдельная типовая проблема — тяжёлый каталог /upload, который либо исключают из архива (и тогда бэкап неполный), либо получают многочасовую задачу с непредсказуемым результатом.
Правило. Бэкап, который выполняется внутри приложения, не переживёт отказ приложения. Серверный бэкап на уровне файловой системы и СУБД работает, даже когда сайт отдаёт 500 или база в аварийном режиме. Средства CMS — приятное дополнение для отката перед обновлением плагина, но не основа защиты данных.
Тест восстановления: главное, что почти никто не делает
Успешно завершившееся задание бэкапа означает только то, что задание завершилось. Оно не означает, что архив полный, что дамп читается, что ключ шифрования подходит и что вы помните порядок действий. Единственная проверка, которая это подтверждает, — фактическое восстановление.
Регламент, который реально выполняется: раз в месяц разворачивать последнюю копию на изолированной площадке — тестовый поддомен, отдельная виртуальная машина или локальное окружение. Замерять реальное время: это и есть ваш настоящий RTO, а не тот, что записан в документе.
# 1. посмотреть, что есть в репозитории
restic snapshots --tag daily --latest 3
# 2. восстановить последний снимок в отдельный каталог
restic restore latest --target /srv/restore-test
# 3. поднять базу в изолированный инстанс и импортировать дамп
mysql -h 127.0.0.1 -e "CREATE DATABASE restore_test CHARACTER SET utf8mb4;"
zcat /srv/restore-test/var/backups/site/db/sitedb-*.sql.gz | mysql -h 127.0.0.1 restore_test
# 4. сверить объём данных с боевым
mysql -h 127.0.0.1 restore_test -e "SELECT COUNT(*) FROM orders; SELECT MAX(created_at) FROM orders;"
# 5. периодически перечитывать часть данных репозитория целиком
restic check --read-data-subset=5%
Чек-лист приёмки восстановленной копии:
- архив распаковывается и расшифровывается имеющимся ключом;
- дамп импортируется без ошибок, содержит все таблицы, включая процедуры и триггеры;
- число записей в ключевых таблицах и максимальная дата совпадают с ожидаемыми;
- сайт отвечает кодом 200, отдаёт корректные заголовки и не сыплет ошибками в лог;
- медиафайлы на месте: выборочно открываются картинки из разных лет;
- работают вход в админку, отправка формы и оформление заказа;
- внешние интеграции подхватывают восстановленные ключи из окружения;
- зафиксировано фактическое время восстановления от начала до рабочего сайта.
Мониторинг самого задания бэкапа
Три сигнала, которые нужно отслеживать, и все три — разные:
- Задание не выполнилось. Отсутствие успешного завершения ловится не логом на сервере (сервер может быть мёртв), а внешним ожиданием сигнала: если пинга нет дольше окна, поднимается тревога. Это классический heartbeat, он же dead man's switch — как его настроить, разобрано в статье про heartbeat-мониторинг cron-задач.
- Бэкап подозрительно маленький. Сравнивайте размер с медианой последних прогонов и поднимайте тревогу при отклонении вниз более чем на 30–40%. Этот сценарий ловит смену пароля к БД, исключённый по ошибке каталог и обрезанный дамп.
- Бэкап не меняется. Если контрольная сумма дампа второй день подряд идентична предыдущей, скорее всего копируется старый файл, а не свежий. Общие подходы к контролю фоновых задач собраны в материале про мониторинг cron-заданий.

Заражение сайта: почему свежий бэкап может уже содержать бэкдор
Автоматический бэкап честно копирует то, что есть на диске, — включая веб-шелл, залитый три недели назад. Если глубина хранения меньше времени присутствия злоумышленника, «чистых» копий у вас нет вообще: восстановление вернёт сайт вместе с закладкой, и через сутки всё повторится.
Отсюда практические выводы:
- Держите глубину. Схема «14 ежедневных + 8 еженедельных + 12 ежемесячных» даёт шанс найти копию старше момента компрометации. Хранение только за последние 7 дней — типичная причина, по которой после взлома откатываться некуда.
- Сначала определите дату компрометации. Логи веб-сервера, время изменения файлов, история платежей и записи в базе дают точку отсчёта. Только после этого выбирают копию — заведомо более раннюю.
- Не восстанавливайте «поверх». Правильный порядок: чистая установка ядра CMS нужной версии из официального дистрибутива, затем перенос только данных — базы и пользовательских загрузок с проверкой загрузок на исполняемые файлы.
- Старый бэкап — это и старые уязвимости. Копия месячной давности содержит непропатченный код, через который и вошли. Обновление и смена всех паролей и ключей должны идти до возврата сайта в онлайн.
- Изолируйте копии от скомпрометированного хоста. Ключ доступа к хранилищу, лежащий на взломанном сервере, позволяет злоумышленнику удалить архивы. Отсюда требование к ключу без права удаления.
Порядок действий после взлома подробно разобран в материалах что делать, если сайт взломали и план реагирования на инцидент. Проверить сайт на вредоносный код до и после восстановления помогает проверка сайта на вирусы и инструмент проверки на вредоносный код.
Как проверить
Восстановление считается завершённым не тогда, когда сайт открылся у вас в браузере, а когда он отвечает корректно снаружи. Проверки, которые стоит прогнать по восстановленной копии и по боевому сайту:
- Проверка HTTP-заголовков — убедитесь, что восстановленная копия отдаёт правильный код ответа, кодировку, заголовки кэширования и безопасности. После восстановления часто теряются заголовки из конфига, который забыли положить в бэкап.
- Проверка скорости загрузки — сравните время ответа с тем, что было до аварии. Резкая просадка означает, что не восстановился кэш, потерялись настройки сжатия или база поднялась без индексов.
- Мониторинг доступности — чтобы узнавать о падении боевого сайта раньше клиентов и запускать восстановление в пределах заявленного RTO.
- Heartbeat для задания бэкапа — внешний сигнал, который приходит после успешного прогона; отсутствие сигнала само по себе становится поводом для тревоги.
- Проверка SSL-сертификата — после восстановления на новом сервере убедитесь, что цепочка сертификатов полная, а автообновление снова работает.
Частые вопросы
Как часто делать бэкап сайта?
Не чаще, чем позволяет канал и нагрузка, и не реже, чем допускает RPO. Для сайта-визитки достаточно раза в сутки. Для магазина с онлайн-оплатой суточный бэкап означает потерю дня заказов — там нужен ежедневный полный бэкап плюс непрерывная архивация журналов транзакций.
Достаточно ли бэкапов, которые делает хостинг?
Как единственная защита — нет. Хостерские копии обычно живут в той же инфраструктуре, имеют небольшую глубину, редко покрывают конфиги и переменные окружения, а условия их предоставления могут меняться. Считайте их удобным дополнением, а не заменой собственной схеме: одна независимая копия под вашим контролем нужна в любом случае.
Чем restic и borg лучше обычного tar по расписанию?
Дедупликацией, шифрованием на клиенте и атомарностью снимков. Каждый снимок восстанавливается независимо, при этом физически хранятся только новые блоки, поэтому глубина в год стоит немногим дороже недели. У обычного архива по расписанию быстро возникает выбор между объёмом и глубиной.
Как проверить бэкап, не разворачивая сайт целиком?
Быстрая проверка — три шага: расшифровать и распаковать архив, убедиться, что логический дамп завершён финальной строкой, и импортировать его в пустую тестовую базу. Это ловит большинство отказов за несколько минут. Но полноценный тест раз в месяц с реальным разворачиванием заменить нельзя: только он проверяет конфиги, права и вашу собственную готовность.
Нужно ли бэкапить сайт, если код лежит в Git?
Да. Git закрывает только код. Пользовательские загрузки, база, конфиги сервера, сертификаты и секреты в репозиторий не попадают — а именно они невосстановимы. Git упрощает бэкап, но не заменяет его.
Куда складывать копии, если бюджет минимальный?
Схема, работающая почти при любом бюджете: короткая локальная копия на сервере для быстрого отката, плюс сжатый и зашифрованный набор в S3-совместимом объектном хранилище с ключом без права удаления. Объём сокращается дедупликацией и разумной политикой хранения, а критичный минимум — дамп базы и загрузки — почти всегда помещается в недорогой тариф.
Чек-лист восстановления после сноса сайта
- Зафиксировать факт и время аварии, не трогая боевой сервер до снятия улик, если есть подозрение на взлом.
- Определить, что именно потеряно: файлы, база, весь сервер, доступ к аккаунту.
- Выбрать копию: последнюю — при отказе оборудования, заведомо более раннюю — при заражении.
- Поднять чистое окружение: ОС, веб-сервер, PHP нужной версии, СУБД. Базовая настройка — по чек-листу первоначальной настройки VPS.
- Восстановить конфиги веб-сервера и PHP, проверить синтаксис до запуска.
- Импортировать базу в изолированный инстанс, проверить число записей и последние даты.
- Развернуть код нужной версии и вернуть пользовательские загрузки, проверив их на исполняемые файлы.
- Восстановить переменные окружения и секреты; при инциденте — сразу сменить все пароли, ключи API и сессии.
- Вернуть сертификаты и убедиться, что автообновление снова работает.
- Восстановить cron и таймеры; проверить, что задания реально запускаются, а не просто присутствуют в файле.
- Прогнать сайт по внутреннему чек-листу: главная, каталог, карточка, корзина, форма, вход в админку.
- Проверить снаружи: коды ответа и заголовки, скорость, сертификат, отсутствие вредоносного кода.
- Переключить трафик (DNS или балансировщик), учитывая TTL записей; порядок шагов — в чек-листе переноса сайта.
- Включить мониторинг доступности и убедиться, что задание бэкапа на новом сервере снова работает и присылает heartbeat.
- Записать фактическое время восстановления и то, что мешало, — это исходные данные для следующего пересмотра RPO и RTO.