Zerobyte на VPS: резервные копии в S3 и проверка восстановления Печать

  • 0

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

Zerobyte помогает настроить резервное копирование через веб-интерфейс: выбрать данные, подключить S3-хранилище, задать расписание и восстановить нужную версию. Разберём установку на Linux VPS и весь путь до контрольного восстановления. Отдельно проверим сценарий, в котором исходный сервер потерян вместе с установленным Zerobyte.

Как устроено резервное копирование в Zerobyte

Zerobyte управляет резервными копиями с помощью Restic. В интерфейсе используются три понятия:

  • Volume — источник данных: например, каталог с файлами сайта.
  • Repository — место хранения зашифрованных копий. В нашем случае это S3.
  • Backup job — задание, которое связывает источник, хранилище, расписание и правила хранения.

При первом запуске передаётся исходный набор данных. При следующих Restic сохраняет новые и изменившиеся блоки, повторно используя уже загруженные. Поэтому ежедневная копия сайта объёмом 50 ГБ не обязательно добавит ещё 50 ГБ в хранилище.

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

Внешнее S3-хранилище должно пережить потерю рабочего сервера. Если развернуть S3-совместимое хранилище на том же VPS и том же диске, такой защиты не получится.

Что подготовить перед установкой

Понадобятся Linux VPS с root-доступом, установленный Docker Engine с Docker Compose, SSH-доступ и отдельный закрытый S3-бакет. Проверьте Docker:

docker --version
docker compose version

До настройки выберите каталоги, без которых проект не запустится. Обычно это файлы приложения, пользовательские загрузки, конфигурация и подготовленная копия базы данных. Для Docker-проекта также нужны Compose-файлы, необходимые переменные окружения и данные постоянных томов.

Заранее ответьте на два вопроса:

  • Сколько данных допустимо потерять? Если потеря заказов за сутки неприемлема, одного ночного бэкапа недостаточно.
  • Сколько времени есть на восстановление? Скачать файлы, импортировать базу и запустить приложение — разные этапы. Учитывайте время на каждый из них.

В примере ниже файлы сайта находятся в /var/www, конфигурация Nginx — в /etc/nginx, а дампы базы будут сохраняться в /srv/backup-staging. Подставьте фактические пути своего проекта. Убедитесь, что каталоги существуют и содержат нужные данные.

Установка Zerobyte на VPS

Команды этого раздела выполняются на VPS. Создайте каталоги и секрет приложения:

sudo -i
install -d -m 700 /opt/zerobyte /var/lib/zerobyte /srv/backup-staging /srv/zerobyte-restore
cd /opt/zerobyte
umask 077
printf 'APP_SECRET=%s\n' "$(openssl rand -hex 32)" > .env

APP_SECRET нужен для шифрования чувствительных настроек в базе Zerobyte. Создавайте его при первой установке. Не перезаписывайте этот файл случайным новым значением при обычном обновлении приложения.

Сохраните в /opt/zerobyte/compose.yaml:

services:
  zerobyte:
    image: ghcr.io/nicotsx/zerobyte:v0.42.0
    restart: unless-stopped
    ports:
      - "127.0.0.1:4096:4096"
    environment:
      TZ: UTC
      BASE_URL: http://localhost:4096
      APP_SECRET: "${APP_SECRET:?Set APP_SECRET in .env}"
    volumes:
      - /var/lib/zerobyte:/var/lib/zerobyte
      - /var/www:/data/www:ro
      - /etc/nginx:/data/nginx:ro
      - /srv/backup-staging:/data/db:ro
      - /srv/zerobyte-restore:/restore

Если вы используете другой веб-сервер, замените подключение /etc/nginx на его конфигурацию. Каталоги проекта, которые находятся за пределами перечисленных путей, нужно подключить отдельными строками.

Источники подключены с :ro: контейнер может читать их, но не изменять. Для восстановления выделен отдельный каталог /restore. Он соответствует /srv/zerobyte-restore на VPS.

Для копирования локальных каталогов в S3 не требуются SYS_ADMIN и /dev/fuse. Они нужны другим сценариям, связанным с монтированием удалённых файловых систем.

Запустите приложение:

docker compose up -d
docker compose ps
docker compose logs --tail=100 zerobyte

Панель слушает только локальный адрес VPS. Чтобы открыть её, выполните на своём компьютере, заменив имя пользователя и адрес сервера:

ssh -N -L 4096:127.0.0.1:4096 user@VPS_IP

Оставьте SSH-соединение открытым и перейдите в браузере на http://localhost:4096. Создайте учётную запись администратора. Если позже решите использовать отдельный домен, настройте HTTPS через обратный прокси и укажите этот адрес в BASE_URL.

Почему базу данных нужно подготовить отдельно

Чтение каталога работающей базы не гарантирует согласованную копию. Пока Zerobyte обходит файлы, СУБД продолжает их менять. Ошибка может обнаружиться только при восстановлении.

Для небольшой MariaDB обычно удобен логический дамп. Например, для первого ручного запуска:

umask 077

if mariadb-dump -u backup -p \
  --single-transaction --quick \
  --routines --events --triggers \
  app_db > /srv/backup-staging/app_db.sql.tmp
then
  mv /srv/backup-staging/app_db.sql.tmp /srv/backup-staging/app_db.sql
else
  printf '%s\n' 'Дамп не создан. Задание Zerobyte запускать нельзя.' >&2
fi

Замените app_db и backup на свою базу и учётную запись с необходимыми правами. Ключ -p запросит пароль. Готовое имя app_db.sql появляется только после успешного завершения дампа.

--single-transaction подходит для согласованного дампа таблиц InnoDB. Он не решает эту задачу для MyISAM; во время дампа также нельзя выполнять изменения структуры таблиц. Учётные записи СУБД и их права нужно учитывать отдельно.

Для PostgreSQL используйте pg_dump; роли и другие глобальные объекты при необходимости сохраняйте через pg_dumpall --globals-only. Проверять такой бэкап нужно импортом в отдельный экземпляр PostgreSQL.

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

Перед включением расписания автоматизируйте подготовку базы. В Zerobyte есть pre-backup HTTP webhook: ошибка этого запроса останавливает запуск копирования. Обработчик должен завершать подготовку дампа до успешного ответа и быть доступен только авторизованному клиенту. Это отдельный HTTP-обработчик, а не поле для произвольной shell-команды.

Два независимых задания «дамп в 01:55, бэкап в 02:00» не гарантируют правильный порядок. Если дамп зависнет или завершится ошибкой, в S3 может снова попасть вчерашний файл. В автоматической схеме проверяйте завершение подготовки и свежесть дампа; таймаут вебхука должен учитывать длительность этой операции.

Подключение S3 и сохранение ключа восстановления

Создайте отдельный приватный бакет и ключ доступа, ограниченный этим бакетом. Не используйте административные ключи от всего облачного аккаунта.

Для обычной работы Restic с Amazon S3 нужны права на перечисление объектов, чтение, запись и удаление. В официальном примере используются ListBucket, GetBucketLocation, GetObject, PutObject и DeleteObject. У другого S3-провайдера проверьте соответствующую политику доступа.

В разделе Repositories создайте репозиторий типа S3-compatible:

Поле Что указать
Name Понятное название, например project-s3.
Endpoint S3 API endpoint вашего провайдера и региона. Не адрес его панели управления.
Bucket Имя подготовленного бакета.
Access Key ID Идентификатор ключа доступа.
Secret Access Key Секретная часть ключа.

Для этой инструкции используйте отдельный пустой бакет. В форме S3 для версии 0.42.0 нет отдельного поля для подпапки репозитория: не дописывайте произвольный путь к имени бакета.

Срок хранения снимков задавайте в Zerobyte. Не добавляйте правило S3 Lifecycle, которое удаляет текущие объекты репозитория просто по возрасту. Старый блок данных может использоваться свежими снимками. Удаление ненужных данных должно учитывать связи внутри Restic-репозитория.

Архивные классы хранения с предварительной разморозкой объектов тоже требуют отдельного плана восстановления. Для первого рабочего бэкапа выбирайте хранилище с немедленным доступом к данным.

Какие секреты понадобятся после потери VPS

Сохраните за пределами сервера, в защищённом хранилище:

  • S3 endpoint, имя бакета и способ получить доступ к нему;
  • restic.pass — скачанный ключ восстановления организации Zerobyte;
  • отдельные пароли импортированных репозиториев, если они отличаются от ключа организации.

Пароль входа в панель, APP_SECRET и restic.pass выполняют разные задачи. Для расшифровки копии нужен пароль именно того Restic-репозитория, который вы открываете.

Для возврата настроек Zerobyte можно дополнительно сохранить экспорт конфигурации .zbex и пароль его шифрования. Храните их отдельно друг от друга. Экспорт настроек не содержит сами резервные копии проекта.

Первый бэкап и расписание

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

Откройте источник в файловом браузере Zerobyte. Проверьте несколько знакомых файлов и наличие свежего дампа. Пустой каталог по ошибочному пути тоже можно успешно скопировать.

Затем в Backups создайте задание, выберите этот источник и S3-репозиторий. Для первого запуска установите Manual only. Добавьте исключение *.tmp, чтобы временный файл незавершённого дампа не попадал в снимок.

Нажмите Backup now. После завершения откройте созданный снимок и проверьте его содержимое. Если есть предупреждения о непрочитанных файлах, разберите их до включения расписания.

После успешного восстановления тестовой копии можно задать расписание. Например, 0 2 * * * означает ежедневный запуск в 02:00. В нашем Compose установлен TZ: UTC, поэтому это 02:00 UTC.

Пример начальной политики хранения для небольшого сайта: Keep Daily — 7, Keep Weekly — 4, Keep Monthly — 3. Правила действуют совместно; один снимок может подходить сразу под несколько. Подберите срок под свой проект: ошибку в данных иногда замечают спустя несколько недель.

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

Нужен и внешний контроль отсутствующих копий. Если VPS выключится, установленный на нём Zerobyte не сможет сообщить о пропущенном задании. Контролируйте время последнего успешного бэкапа из независимой системы мониторинга.

Как проверить восстановление через Zerobyte

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

  1. Откройте задание и выберите снимок по дате.
  2. Выберите небольшой каталог или несколько нужных файлов.
  3. Откройте восстановление и выберите Custom location.
  4. Укажите /restore. В нашем примере результат появится внутри /srv/zerobyte-restore на VPS.
  5. Проверьте режим перезаписи и запустите восстановление.
  6. Дождитесь завершения и проверьте файлы на диске.

Путь назначения здесь относится к контейнеру. Произвольный каталог внутри контейнера без подключения к диску VPS неудобен для проверки и может исчезнуть при пересоздании контейнера.

Для проверки содержимого выберите файл, который не менялся после создания снимка, и сравните его SHA-256 с восстановленным экземпляром через sha256sum. Совпадение хешей подтверждает совпадение содержимого этого файла. Владельца, группу и права доступа проверяйте отдельно.

Затем восстановите весь необходимый набор и запустите проект в изолированной среде:

  • импортируйте дамп в отдельную тестовую СУБД;
  • подключите приложение к тестовой базе;
  • проверьте вход, открытие существующих данных и создание новой записи;
  • откройте пользовательские загрузки;
  • проверьте права на каталоги, в которые приложение должно записывать данные.

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

Для такой репетиции удобно использовать отдельный Linux-сервер. На VPS QDC с root-доступом можно установить нужное окружение и проверить проект независимо от рабочего сервера. При выборе ресурсов предусмотрите место для восстановленных файлов, развёрнутой базы и временных данных импорта.

Запишите дату снимка, результат проверки и фактическое время восстановления. Например, «файлы получены, база импортирована, вход и загрузки работают, запуск занял 48 минут» — полезная запись. Это пример формата отчёта, а не обещание времени восстановления.

Как восстановить данные, если VPS и Zerobyte потеряны

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

На отдельном Linux-сервере установите Restic и безопасно перенесите файл restic.pass, например в /root/restore-secrets/restic.pass. Ограничьте доступ к каталогу и файлу. Следующий пример рассчитан на Bash и выполнение от root:

chmod 700 /root/restore-secrets
chmod 600 /root/restore-secrets/restic.pass

export RESTIC_REPOSITORY='s3:https://s3.example.net/project-backups'
export RESTIC_PASSWORD_FILE='/root/restore-secrets/restic.pass'

read -r -p 'S3 Access Key ID: ' AWS_ACCESS_KEY_ID
read -r -s -p 'S3 Secret Access Key: ' AWS_SECRET_ACCESS_KEY
printf '\n'
export AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY

restic snapshots

Замените endpoint и бакет на свои. Если провайдер требует явного указания региона, задайте AWS_DEFAULT_REGION. Для импортированного репозитория с отдельным паролем понадобится файл именно с этим паролем.

Если команда показывает ожидаемые снимки, доступ к хранилищу и пароль репозитория работают. Выберите нужный снимок по дате и составу данных. Подставьте его идентификатор вместо SNAPSHOT_ID:

restic ls SNAPSHOT_ID
restic restore SNAPSHOT_ID --target /srv/restore-drill

Используйте новый пустой каталог назначения. Структуру путей внутри снимка сначала посмотрите через restic ls: путь восстановленного файла может включать исходные каталоги.

Не запускайте restic init для поиска старых копий. Эта команда создаёт репозиторий; для восстановления нужно подключиться к существующему.

После получения файлов повторите проверку приложения и базы данных. Если всё запускается без обращения к старому VPS, вы проверили главное условие аварийного восстановления.

Почему Doctor не заменяет проверку восстановления

Встроенный Doctor выполняет обслуживание репозитория: снимает устаревшие блокировки, запускает restic check и при необходимости восстанавливает индекс. Полное чтение всех сохранённых данных в эту процедуру не входит.

Для проверки содержимого всех пакетов репозитория используется отдельная команда. Выполняйте её с настроенными переменными доступа из предыдущего раздела, в согласованное окно обслуживания:

restic check --read-data

Она читает все пакеты данных, поэтому может занять много времени и увеличить расходы на запросы и исходящий трафик S3. Для поэтапной проверки Restic поддерживает --read-data-subset.

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

Частые ошибки и что делать

AccessDenied при подключении к S3

Проверьте ключ, бакет, endpoint и ограничения политики доступа. Возможность загружать объекты не означает, что разрешено читать их или выполнять очистку. Если ошибка появляется на определённом этапе, найдите в журнале операцию, которую отклонило хранилище. Не исправляйте доступ включением публичного чтения бакета.

Permission denied или Read-only file system при восстановлении

Проверьте каталог назначения. В примере источники подключены с :ro, поэтому восстановление в них запрещено. Используйте /restore. Если ошибка относится к chown, chmod или атрибутам файлов на сетевом ресурсе, сначала восстановите данные на локальную Linux-файловую систему, затем разберите перенос прав.

Repository is locked

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

Задание успешно, но в копии нет нужных файлов

Проверьте путь внутри контейнера, подключение каталога в Compose и правила исключения. Затем откройте сам снимок. Если в нём только пустые каталоги или старый дамп, повторный запуск без исправления источника ничего не решит.

Восстановление оказалось слишком долгим

Посмотрите, где уходит время: на получение данных из S3, запись на диск, импорт базы или запуск приложения. Только передача 100 ГБ со средней скоростью 10 МБ/с займёт примерно 2 часа 47 минут, без учёта остальных этапов. Это расчётный пример; реальную скорость измеряйте на своей копии.

Если допустимое время простоя меньше, заранее подготовьте окружение для восстановления или дополнительную доступную копию ближе к месту запуска.

Что ещё важно знать

Достаточно ли одного S3-бэкапа?

Рабочие данные и одна копия в S3 — это две копии. Для более устойчивой схемы нужна ещё одна независимая копия с подходящим размещением и отдельным управлением доступом. Сам факт отправки данных в S3 не означает выполнение правила 3-2-1.

Защищает ли шифрование от удаления резервных копий?

Шифрование защищает содержимое от чтения без пароля. Ключ S3 с правом удаления по-прежнему позволяет удалить объекты. Для защиты от такого сценария отдельно продумывают независимые копии, версии объектов или Object Lock. Совместимость блокировок с очисткой Restic нужно проверить до включения на основном репозитории.

Что делать, если потерян restic.pass?

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

После настройки проведите первое восстановление, пока рабочий сервер доступен и есть с чем сравнить результат. Повторяйте проверку после смены хранилища, обновления схемы резервного копирования и существенных изменений приложения. У исправной системы бэкапов должен быть понятный ответ не только на вопрос «когда создана копия», но и на вопрос «когда из неё последний раз удалось запустить проект».


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

« Назад