MAATRIX / Блог / Антипаттерн: бэкап лежит на том же сервере

Антипаттерн: бэкап лежит на том же сервере

MAATRIX

Cron исправно отрабатывает каждую ночь, в директории /home/backups/ растёт аккуратный ряд файлов с датами в имени, и всё выглядит так, будто резервное копирование настроено и работает. Проблема в том, что эта копия лежит на том же физическом сервере, что и данные, которые она должна спасти — а значит, она не переживёт ни один из сценариев, ради которых бэкапы вообще делают. Разберём, как именно это выглядит в реальных конфигурациях, что именно ломается и как перенести копию туда, где она реально защитит данные.

Типичный cron-скрипт: как выглядит "бэкап, который вроде есть"

Вот классический пример — /etc/cron.d/backup-db на продакшн-сервере с PostgreSQL:

0 3 * * * postgres pg_dump -Fc mydb > /home/backups/db_$(date +\%F).sql.gz

Или вариант для файлов сайта:

#!/bin/bash
# /usr/local/bin/backup-site.sh
tar czf /backup/site_backup_$(date +%F).tar.gz /var/www/site
find /backup -name "site_backup_*.tar.gz" -mtime +7 -delete

Оба скрипта делают ровно то, что от них ждут: pg_dump выгружает базу, tar архивирует файлы сайта, find подчищает старьё. Задача поставлена в cron, письма об ошибках не приходят, размер /backup растёт предсказуемо. Разработчик или админ смотрит на это и делает вывод: "бэкап есть, он регулярный, всё под контролем". И именно в этом моменте закрадывается ошибка — потому что вопрос "куда именно сохранён бэкап" остаётся без ответа. А ответ здесь: /home/backups и /var/www/site физически находятся на одном и том же диске одного и того же сервера.

Та же логика встречается и в конфигах "продвинутых" инструментов, если их не донастроить. Например, в BorgBackup репозиторий по умолчанию создают локально:

borg init --encryption=repokey /backup/borg-repo
borg create /backup/borg-repo::'{hostname}-{now}' /var/www /etc /home

Шифрование есть, дедупликация есть, инкрементальность есть — но репозиторий /backup/borg-repo снова лежит на том же сервере, что и /var/www. Инструмент правильный, а размещение — нет.

Почему это не бэкап, а копия рядом с оригиналом

Смысл резервного копирования — не в том, чтобы иметь второй экземпляр файла, а в том, чтобы иметь его в независимой точке отказа. Если оригинал и копия зависят от одного и того же диска, одного и того же контроллера, одного и того же питания и одной и той же учётной записи root на сервере — это не резервная копия в инженерном смысле, а просто ещё один файл рядом с первым. Оба погибают по одной и той же причине одновременно.

Это тот же корень проблемы, что и в статье про RAID — RAID не является резервной копией: избыточность внутри одного сервера защищает от отказа одного диска, но не от отказа сервера целиком. Бэкап на соседней директории того же сервера страдает точно от той же болезни, только на уровне файловой системы, а не блочных устройств.

Дальше — три конкретных сценария, в которых эта разница между "копия есть" и "копия защищает" становится критичной.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Сценарий 1: сервер отказал целиком

RAID-массив, отдельный раздел под бэкапы, даже второй физический диск в том же корпусе — ничего из этого не спасает, если выходит из строя не диск, а сервер как единица. А поводов для этого достаточно:

  • отказ материнской платы или блока питания — сервер не включается, диски физически исправны, но недоступны без замены железа;
  • пожар, залив, кража оборудования из стойки — сама физика уничтожена вместе со всем содержимым;
  • взлом с полным удалением файловой системы — злоумышленник, получивший root, стирает / целиком, не разбирая, где данные, а где их копии;
  • ошибка провайдера или хостера — редко, но встречается: снос не того VPS, потеря диска при миграции без предупреждения.

Во всех этих случаях RAID на этом же сервере не спасает, потому что отказывает не отдельный диск массива, а сервер целиком — вместе со всеми дисками, которые к нему подключены. Ваш /home/backups пропадает синхронно с /var/lib/postgresql. Формально бэкап "был", по факту он умер в ту же секунду, что и оригинал.

Сценарий 2: взлом через приложение и шифровальщик

Второй сценарий даже неприятнее первого, потому что не требует полного отказа сервера — достаточно скомпрометировать один процесс. Классическая цепочка: уязвимость в веб-приложении (устаревший плагин CMS, необновлённая библиотека, открытый эндпоинт с RCE) даёт атакующему возможность выполнять код от имени пользователя, под которым крутится сайт или база.

Если этот пользователь — тот же самый www-data или postgres, у которого есть права на запись в /backup или /home/backups (а чаще всего именно так и настроено, потому что "иначе как cron туда запишет"), атакующий получает доступ и к оригиналу, и к его резервным копиям одним и тем же вектором. Программа-шифровальщик, попавшая на сервер, не разбирает, что перед ней "продакшн" и что "бэкап" — она рекурсивно проходит по доступным для записи директориям и шифрует всё, до чего дотягивается. /var/www/site и лежащий рядом /backup/site_backup_2026-08-15.tar.gz шифруются в одном проходе.

Итог: жертва, у которой "были бэкапы", после инцидента обнаруживает, что зашифрованы и данные, и все копии за последние недели, потому что ротация (find ... -mtime +7 -delete) заботливо удалила старые версии ещё до атаки, а свежие достались шифровальщику. Разбор похожих историй есть в статье что делать при взломе сервера — там же видно, почему первый пункт плана реагирования это всегда "откуда восстанавливаемся, если сам сервер под подозрением".

Сценарий 3: бэкапы забивают диск и роняют прод

Третий сценарий не про катастрофу, а про медленную деградацию, которую легко проглядеть. Бэкапы на том же диске конкурируют с продакшном за одно и то же место. Если ротацию забыли настроить или настроили неправильно (типичная ошибка — mtime +7 вместо mtime -7 в find, из-за чего удаляются свежие файлы, а старые остаются), директория с архивами растёт без ограничений.

Дальше события развиваются по одному из двух сценариев:

  • диск заполняется целиком, и pg_dump или tar падает с ошибкой No space left on device посреди выполнения, оставляя битый, недописанный архив — при этом само приложение тоже может начать сбоить, если ему самому нужно место для временных файлов, логов или WAL;
  • на дисках с включённым CoW (например, ZFS, Btrfs) снапшоты или дедуплицированные блоки бэкапа незаметно съедают место, которое приложение считало свободным, и в момент пиковой нагрузки (рост таблицы, загрузка файлов пользователями) продакшн внезапно упирается в лимит.

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

Как сделать правильно: 3-2-1 и перенос на другой сервер

Правильная схема описывается простым и проверенным временем правилом 3-2-1: минимум 3 копии данных, на 2 разных типах носителей, и как минимум 1 копия — физически в другом месте. На практике для VPS и выделенных серверов это разворачивается так:

  1. Копия 1 — оригинальные данные на рабочем сервере.
  2. Копия 2 — локальный бэкап на том же сервере (для быстрого восстановления после случайной ошибки — удалили таблицу, откатили деплой). Держать его можно, но он не считается защитой от отказа сервера, это просто удобство.
  3. Копия 3 — синхронизация на другой физический сервер или в объектное хранилище, географически и организационно независимое от первого.

Именно пункт 3 закрывает все три сценария выше. Реализуется он одним из двух способов.

Синхронизация на отдельный сервер-приёмник через rsync поверх SSH:

# на сервере с данными, после того как локальный архив создан
rsync -avz --delete /backup/ remote-backup-host:/backups/prod-server/

Ключ -avz сохраняет права и атрибуты, сжимает трафик на лету; --delete синхронизирует состав каталогов, если старые архивы удалены локальной ротацией. Для автоматизации команду добавляют отдельной строкой в тот же cron-скрипт, сразу после создания архива, и настраивают аутентификацию по SSH-ключу без пароля (с ограниченным по command= доступом на стороне приёмника — только на запись в конкретную директорию).

Отправка в объектное хранилище, совместимое с S3, через rclone или aws-cli:

# однократная настройка удалённого хранилища
rclone config

# отправка архива после его создания
rclone copy /backup/db_2026-08-30.sql.gz remote-s3:my-backups-bucket/db/

# то же самое через aws-cli, если хранилище отдаёт S3 API
aws s3 cp /backup/db_2026-08-30.sql.gz s3://my-backups-bucket/db/

Подробнее про настройку самого rclone — в статье как установить и настроить rclone на VPS. Важное условие для обоих вариантов: сервер-приёмник (или бакет) должен быть у другого провайдера или как минимум в другом дата-центре, с отдельными учётными данными, не пересекающимися с теми, которыми пользуется скомпрометированное в сценарии 2 приложение. Если для синхронизации используется тот же SSH-ключ, что даёт root-доступ на продакшн, часть защиты от взлома теряется — цепочка компрометации может дотянуться и туда.

Отдельный сервер под бэкапы удобно арендовать именно под эту задачу — минимальные требования по CPU, но нужен объём диска и надёжная сеть для регулярной синхронизации; подробнее в статье VPS для бэкапов и архива: что выбрать и как настроить.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Если у меня RAID1 на сервере, разве этого не достаточно как второй копии?

Нет — RAID защищает от отказа одного диска, но не от отказа сервера целиком (материнская плата, питание, кража, полный снос файловой системы при взломе). Это первая, а не третья копия из правила 3-2-1.

Можно ли просто хранить бэкап в другой директории того же диска, если больше некуда?

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

Обязательно ли использовать именно rsync или rclone, а не что-то ещё?

Нет, важен принцип — копия должна оказаться на независимом физическом носителе, недоступном тем же учётным данным, что и продакшн. Конкретный инструмент (rsync, rclone, aws s3 cp, restic с удалённым репозиторием, BorgBackup с SSH-репозиторием на другом хосте) выбирается под удобство и уже используемый стек.

Как часто нужно проверять, что синхронизация на удалённый сервер реально работает?

Регулярно и осмысленно — мониторить не только факт запуска задачи, но и успешность передачи (код возврата rsync/rclone) и хотя бы изредка делать тестовое восстановление из удалённой копии, а не только из локальной.

Что делать, если места на удалённом сервере меньше, чем накопилось локальных архивов?

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

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →