Резервное копирование 3-2-1 для небольшой компании

На первом аудите мы почти всегда слышим «копии у нас есть». Примерно в половине случаев выясняется, что они лежат на диске, подключённом к тому же серверу, и не проверялись с момента настройки. Разбираем, как сделать по-настоящему.

Правило 3-2-1 и его продолжение

Формулировка простая:

  • 3 копии данных: рабочая и две резервные;
  • 2 разных носителя или системы хранения: например, сервер и отдельное сетевое хранилище;
  • 1 копия вне площадки: в другом здании, городе или у провайдера хранения.

За последние годы к правилу добавили ещё две цифры — получилось 3-2-1-1-0: одна копия неизменяемая или отключённая от сети (её не удалить и не зашифровать даже с правами администратора) и 0 ошибок при проверке восстановления. Именно последние две цифры отличают резервное копирование от его имитации.

Рабочий сервер копия № 1 · база учёта Хранилище в офисе копия № 2 · другой носитель каждый час Удалённое хранилище копия № 3 · другой город каждую ночь Только добавление удалить старые снимки с сервера нельзя Тестовый стенд восстановление раз в месяц
Схема, которую мы ставим большинству клиентов на тарифе «Старт»

Что именно копировать

Начинать стоит не с программы, а со списка. Для каждой системы ответьте на два вопроса:

  • RPO — сколько данных можно потерять? Час работы бухгалтерии? День? Неделю фотографий товаров?
  • RTO — за сколько нужно восстановиться? Кассы магазина — за полчаса, архив договоров — за день.
ЧтоКак частоСколько хранитьОсобенности
Базы учёта, PostgreSQL, MS SQLкаждый час — каждые 15 мин14 дней по часам, 12 месяцев по месяцамКопировать дамп, а не файлы работающей базы
Файловый серверкаждый час30 дней, затем помесячно годХорошо дедуплицируется
Конфигурация серверов и сетипри каждом изменениибессрочноУдобно хранить в git
Почта, облачные документыраз в суткипо требованиям бизнеса«Облако» ≠ резервная копия
Журналы датчиков и камерраз в суткипо нормативу (часто 3 года)Объём растёт быстро — считайте заранее

Самая частая ошибка — копировать файлы базы данных, пока она работает. Такая копия может не открыться. Сначала делайте согласованный дамп (pg_dump, встроенное резервное копирование MS SQL) и копируйте уже его.

Настройка на restic

Для Linux-серверов мы чаще всего используем restic: он шифрует данные на стороне клиента, дедуплицирует, умеет писать в SFTP, S3-совместимые хранилища и на собственный сервер rest-server. Создаём репозиторий на хранилище в офисе:

# /etc/restic/office.env — права 600, владелец root
RESTIC_REPOSITORY=sftp:backup@nas.office.lan:/srv/restic/srv-db01
RESTIC_PASSWORD_FILE=/etc/restic/office.pass
sudo sh -c 'umask 077; openssl rand -base64 32 > /etc/restic/office.pass'
sudo sh -c 'set -a; . /etc/restic/office.env; restic init'

Пароль репозитория — единственный способ расшифровать копии. Сохраните его в хранилище паролей компании и на бумаге в сейфе. Без него копия бесполезна.

Скрипт копирования: сначала дамп базы, потом снимок, потом очистка по политике хранения.

#!/bin/sh
# /usr/local/sbin/backup-office
set -eu
. /etc/restic/office.env
export RESTIC_REPOSITORY RESTIC_PASSWORD_FILE

# 1. Согласованный дамп базы
install -d -m 700 /var/backups/pg
sudo -u postgres pg_dump -Fc shop > /var/backups/pg/shop.dump

# 2. Снимок
restic backup /etc /srv/files /var/backups/pg \
  --exclude-caches --exclude '/srv/files/**/*.tmp' \
  --tag hourly

# 3. Политика хранения
restic forget --tag hourly \
  --keep-hourly 48 --keep-daily 14 --keep-weekly 8 --keep-monthly 12 \
  --prune

Запускаем по таймеру systemd — он, в отличие от cron, пишет результат в журнал и не запустит вторую копию, пока не закончилась первая:

# /etc/systemd/system/backup-office.service
[Unit]
Description=Резервное копирование на хранилище в офисе
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup-office
Nice=10
IOSchedulingClass=idle

# /etc/systemd/system/backup-office.timer
[Unit]
Description=Ежечасное резервное копирование

[Timer]
OnCalendar=hourly
RandomizedDelaySec=10m
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup-office.timer
systemctl list-timers backup-office.timer

Для удалённой копии создаётся второй репозиторий с другим паролем и отдельным таймером — ночью, когда канал свободен.

Защита от шифровальщика

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

  • rest-server --append-only — сервер принимает новые снимки, но не даёт удалять существующие. Очистку (forget --prune) запускаем с другой машины с отдельными учётными данными.
  • Для S3-совместимых хранилищ — неизменяемые объекты (Object Lock) со сроком хранения 30 дней, если провайдер это поддерживает.
  • Самый простой вариант для маленького офиса — два внешних диска, которые меняются раз в неделю, и один всегда лежит не подключённым в другом месте.

Проверка восстановления

Целостность репозитория проверяется командой restic check. Раз в неделю имеет смысл читать и часть самих данных:

# каждую неделю — своя 1/20 часть данных: за 20 недель прочитается весь репозиторий
restic check --read-data-subset=$(( $(date +%-V) % 20 + 1 ))/20

Но настоящая проверка — восстановить и запустить. Раз в месяц мы берём случайный снимок, разворачиваем его на тестовой машине и проверяем, что приложение работает:

restic snapshots --tag hourly --latest 3
restic restore latest --target /restore-test --include /var/backups/pg
sudo -u postgres createdb shop_restore_test
sudo -u postgres pg_restore -d shop_restore_test /restore-test/var/backups/pg/shop.dump
sudo -u postgres psql -d shop_restore_test -c "select count(*), max(created_at) from orders;"

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

Минимум, который стоит сделать на этой неделе

  • Составить список систем с RPO и RTO.
  • Убедиться, что хотя бы одна копия лежит не в том же здании.
  • Проверить, что сервер не может удалить удалённую копию.
  • Восстановить что-нибудь одно и засечь время.
  • Положить пароль от репозитория туда, где его найдут без вас.