
Удалённое хранилище
Копия, которая лежит на той же машине, что и сайт, защищает от испорченной базы, неудачного обновления и ошибки контент-менеджера. Она не защищает от потери самой машины: сгоревший диск, закрытый аккаунт у хостера или удалённый сервер забирают сайт вместе со всеми его копиями.
Начиная с версии 1.4.0-rc mxBackup умеет выгружать готовый архив в S3 или совместимое хранилище сразу после создания.
Версия для MODX 3
В линии 2.x (MODX 3) удалённого хранилища пока нет — оно появится отдельным релизом. Всё, что описано на этой странице, относится к линии 1.x.
Что это даёт
- Копия уезжает с машины в момент создания, а не «когда-нибудь потом руками».
- Диск не забивается: после успешной выгрузки на сервере остаётся столько копий, сколько вы указали, — остальные уже в облаке.
- Восстановление одной командой прямо из хранилища, без ручной выкачки.
Настройка
Хранилище задаётся профилем, а не общей настройкой. Это сделано намеренно: у профилей разное назначение. Боевая копия обязана уезжать с сервера, а обезличенная копия для разработки нужна тут же под рукой — платить за её хранение и трафик незачем.
В менеджере откройте профиль и разверните блок «Удалённое хранилище».
| Поле | Что означает |
|---|---|
| Хранилище | S3 — выгружать, «выключено» — копия остаётся на сервере |
| Бакет | имя бакета |
| Регион | например eu-central-1 |
| Префикс ключа | папка внутри бакета, например stage/; пусто — корень |
| Endpoint | адрес S3-совместимого сервиса; пусто — Amazon S3 |
| Класс хранения | STANDARD_IA, GLACIER_IR и подобные; пусто — класс по умолчанию |
| Access key / Secret key | ключи доступа; можно оставить пустыми, см. ниже |
| Копий на диске | сколько последних архивов оставлять на сервере, минимум 1 |
| Хранить в облаке дней / архивов | глубина хранения; 0 в обоих полях — не удалять ничего |
То же самое в файле профиля:
return [
'name' => 'prod',
'mode' => 'prod',
'format' => 'zip',
'remote' => [
'driver' => 's3',
'keep_local' => 2,
'retention' => ['days' => 30, 'count' => 0],
's3' => [
'bucket' => 'my-site-backups',
'region' => 'eu-central-1',
'prefix' => 'prod/',
'endpoint' => '',
'storage_class' => '',
'access_key' => '',
'secret_key' => '',
],
],
// остальные секции профиля
];Значения по средам
Файл профиля обычно лежит в системе контроля версий и одинаков на всех серверах, а бакет у стенда и у боевого сайта разный. Профиль — обычный PHP, поэтому значения удобно брать из окружения:
'bucket' => (string) (getenv('BACKUP_BUCKET') ?: ''),
'prefix' => (string) (getenv('APP_ENV') ?: 'unknown') . '/',Пустой бакет означает «копия остаётся на машине» — так ведут себя локальные копии разработчиков.
Проверка доступа
Не дожидаясь ночного запуска:
php core/components/mxbackup/cli/mxbackup.php remote-check --profile=prod
php core/components/mxbackup/cli/mxbackup.php remote-check --profile=prod --writeБез ключа проверяется только чтение. С --write пакет кладёт в хранилище пробный объект и тут же удаляет его — так видно, хватает ли прав на запись и на удаление. Прав на удаление может не быть намеренно (см. ниже); тогда команда об этом скажет, а пробный объект придётся убрать вручную.
Доступ без ключей
Ключи в профиле — не единственный способ. Пакет ищет учётные данные по цепочке:
- поля профиля — самый явный способ, годится где угодно;
- переменные окружения
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_SESSION_TOKEN— обычный путь для контейнеров и CI; - роль машины в облаке — если сайт работает на инстансе AWS, доступ выдаётся роли инстанса, и ключей на сервере нет вовсе.
Третий вариант предпочтительнее остальных: временные учётные данные живут около часа и запрашиваются у сервиса метаданных при каждом запуске, поэтому украденный файл профиля не даёт доступа к бакету.
Ключи в профиле хранятся открыто
Как и пароль AES-шифрования, ключ лежит в PHP-файле профиля в открытом виде — файл создаётся с правами 0640. Обратно в интерфейсе ключ не показывается: пустое поле означает «не менять», а не «стереть». Если поле «Access key» очистить осознанно, секрет сбрасывается вместе с ним, и доступ начнёт браться из окружения или роли машины.
Что происходит при запуске
Порядок такой: архив создаётся на диске → проверяется контрольной суммой → выгружается → чистятся старые копии, сначала в хранилище, потом на диске.
Объект получает метки с контрольной суммой архива, именем профиля и версией пакета — по ним видно, что скачали именно то, что паковали, не разворачивая архив.
Неудачная выгрузка не отменяет копию
Если хранилище недоступно, запуск завершится предупреждением, а не ошибкой: архив создан и лежит на диске, то есть работа сделана. Локальные копии в этом случае не удаляются по правилу «копий на диске» — удалять то, что никуда не уехало, нельзя.
Последний архив остаётся на сервере всегда, даже если поставить «копий на диске» в минимум: восстановление из него не зависит ни от сети, ни от того, жив ли доступ к хранилищу.
Глубина хранения
Правил два, и они независимы: сколько копий держать на диске и сколько — в хранилище.
Глубина в облаке по умолчанию не ограничена ничем — пакет там не удаляет ничего. Это сделано сознательно: у бакета может быть собственное правило истечения (lifecycle), и две ротации, не знающие друг о друге, ведут себя хуже одной. Если своего правила у бакета нет — задайте глубину в профиле.
Как и локальная ротация, удалённая защищает свежие копии: указанное количество последних архивов не удаляется даже когда они старше заданного срока. Иначе остановившийся cron через несколько недель оставил бы сайт вовсе без копий.
Что лежит в хранилище
php core/components/mxbackup/cli/mxbackup.php remote-list --profile=prodКоманда возвращает список архивов профиля с размерами и датами. Чужие объекты под тем же префиксом пакет не показывает и не трогает: бакет может быть общим.
Восстановление из облака
php core/components/mxbackup/cli/mxbackup.php restore-check --profile=prod \
--from-remote=mxbackup-prod-20260808-020000.zipАрхив скачивается в каталог хранения и дальше проходит обычный путь: preflight, код подтверждения и восстановление. Ключ --from-remote работает и с restore.
Если файл с таким именем уже есть на диске, команда откажется его перезаписывать и предложит указать локальный путь через --archive — так исключается случай, когда скачанная копия молча затирает ту, из которой вы собирались восстанавливаться.
Совместимые хранилища
Кроме Amazon S3 подходят MinIO, Selectel, Yandex Object Storage и другие сервисы с S3-совместимым API: укажите их адрес в поле Endpoint, и пакет переключится на адресацию с именем бакета в пути. Регион всё равно нужен — он входит в подпись запроса; если сервис его не использует, подойдёт любое значение, например us-east-1.
Ограничения
Архив выгружается одним запросом, без составной загрузки, поэтому предельный размер — 5 ГБ. Копии такого размера в PHP-процессе обычно не собираются и по другим причинам: памяти, времени выполнения и лимитов хостинга.
