119 lines
7.9 KiB
Markdown
119 lines
7.9 KiB
Markdown
# Backup и восстановление — Phase 5
|
||
|
||
`./mcpack backup` работает с полным релизом и runtime, который уже связан
|
||
с ним через `scripts/server.sh`. Нужны Node/npm dependencies, закреплённый
|
||
Compose, Docker daemon, GNU tar и zstd. Оператор должен читать весь runtime
|
||
и сохранять владельцев при распаковке: запускать от владельца данных или
|
||
с необходимыми правами. Проверка UID/GID не пропускается.
|
||
|
||
## Создание snapshot
|
||
|
||
```bash
|
||
export MC_ROOT=/absolute/server-root
|
||
export MC_RELEASE_DIR=/absolute/full-release
|
||
# MC_ENV_FILE — необязательный абсолютный путь, по умолчанию MC_ROOT/.env.
|
||
./mcpack backup --wait-timeout 120
|
||
```
|
||
|
||
Команда удерживает общую `.mcpack-runtime.lock`, проверяет релиз/settings,
|
||
останавливает сервер через Compose и подтверждает остановку по Docker state.
|
||
После этого архивирует **весь `MC_ROOT/runtime` без исключений**: world,
|
||
данные модов вне world, конфиги, server.properties, whitelist/operators,
|
||
логи, cache, downloads и установленные server/mod JAR. Для NeoForge безопасные
|
||
исключения пока не подтверждены. Releases, snapshots и host `.env` находятся
|
||
вне runtime и не входят в архив; внутри snapshot хранится отдельная полная
|
||
копия исходного релиза, включая его `.env.example`.
|
||
|
||
Результат находится в `MC_ROOT/backups/<UTC timestamp>-<UUID>/`:
|
||
|
||
```text
|
||
runtime.tar.zst
|
||
metadata.json
|
||
SHA256SUMS
|
||
release/ # исходный полный релиз с собственными checksums
|
||
```
|
||
|
||
Metadata фиксирует исходный релиз, SHA256 manifest/checksum list, закреплённый
|
||
image, целевой релиз (если передан `--target-release /absolute/release`),
|
||
прежнее состояние сервера, подтверждение остановки, время, исключения,
|
||
архив SHA256/размер и inventory путей/хешей/размеров/mode/UID/GID runtime.
|
||
`--target-release` только проверяет и записывает назначение будущего deployment;
|
||
команда backup сама не применяет новый релиз.
|
||
|
||
Перед публикацией выполняются tar/zstd listing, проверка типов/путей и
|
||
пробная распаковка с точным сравнением inventory. Checksums покрывают все
|
||
файлы snapshot и сохранённого релиза. Каталог публикуется атомарным rename
|
||
внутри backups; незавершённый snapshot не появляется под окончательным именем.
|
||
При успехе ранее запущенный сервер возвращается на тот же релиз через
|
||
`up --wait`. Остановленный сервер или отсутствующий контейнер не запускаются.
|
||
|
||
Ошибка backup возвращает non-zero. При ошибке после успешной остановки сервер
|
||
остаётся остановленным; оператор получает ошибку и status в
|
||
`MC_ROOT/.mcpack-backup-operation.json`. Ошибка resume сохраняет опубликованный
|
||
проверенный snapshot и пытается снова остановить сервер. Новый deployment
|
||
должен использовать `backupBeforeApply` из `platform/backups.mjs`: callback
|
||
применения допускается только после публикации snapshot и под той же блокировкой.
|
||
Этот gate проверен тестами и используется SSH deployment Phase 7 под общей
|
||
блокировкой всей операции: [deploy.md](deploy.md).
|
||
|
||
Snapshot не удаляется автоматически. Нужны свободное место под полный runtime,
|
||
пробную распаковку и копию релиза; операция завершается ошибкой при нехватке места.
|
||
Символические/жёсткие ссылки и специальные файлы в runtime сейчас отклоняются.
|
||
Команды вне wrapper не участвуют в блокировке; во время backup не изменять
|
||
runtime вручную и не запускать контейнер прямым Compose.
|
||
|
||
## Восстановление в отдельный каталог
|
||
|
||
```bash
|
||
./mcpack restore \
|
||
--backup /absolute/server-root/backups/TIMESTAMP-UUID \
|
||
--destination /absolute/restored-server
|
||
```
|
||
|
||
Destination должен **не существовать**. Команда сначала проверяет snapshot,
|
||
распаковывает во временный соседний каталог, сверяет bytes/mode/UID/GID,
|
||
проверяет сохранённый релиз и публикует новый root атомарным rename.
|
||
Исходный runtime не изменяется. Результат:
|
||
|
||
```text
|
||
restored-server/runtime/
|
||
restored-server/release/
|
||
restored-server/.mcpack-runtime.json
|
||
restored-server/restore-report.json
|
||
```
|
||
|
||
Host settings и EULA acceptance из snapshot не восстанавливаются; сервер
|
||
автоматически не запускается. Для ручного recovery подготовить `.env` из
|
||
`release/server/.env.example`, задать прежние UID/GID, подходящие memory/port
|
||
и принятие EULA. Используется прежний стабильный Compose project из binding.
|
||
Прежде чем запускать восстановленную копию под тем же project, остановить
|
||
и удалить **старый контейнер** через wrapper (данные старого root сохраняются):
|
||
|
||
```bash
|
||
MC_ROOT=/absolute/original-server \
|
||
MC_RELEASE_DIR=/absolute/original-release scripts/server.sh down
|
||
|
||
# На данном host settings уже настроены и EULA принята:
|
||
export MC_ROOT=/absolute/restored-server
|
||
export MC_RELEASE_DIR="$MC_ROOT/release"
|
||
export MC_ENV_FILE=/absolute/prepared-host-settings.env
|
||
scripts/server.sh up -d --wait --wait-timeout 120
|
||
scripts/server.sh exec -T minecraft mc-health
|
||
scripts/server.sh logs --tail 100
|
||
```
|
||
|
||
Не заменять binding или release на более новую версию: восстановленный мир
|
||
нужно запускать с сохранённым исходным релизом. Если прежний контейнер ещё
|
||
использует другой root, wrapper отклонит запуск. Это ручное восстановление
|
||
в отдельный root; переключение active release и rollback — последующие фазы.
|
||
|
||
## Область проверки
|
||
|
||
Проверен local Linux/WSL Docker и NeoForge 21.1.252 / Minecraft 1.21.1.
|
||
Primary Phase 0 runtime пока управляется старым spike wrapper без full-release
|
||
binding, поэтому его миграция не выполняется этой командой. Off-host копии,
|
||
retention, автоматический rollback и защита от внезапного отключения питания
|
||
во время записи (fsync) остаются последующими улучшениями.
|
||
|
||
Реальный опыт восстановления и свидетельства: [phase5-results.md](phase5-results.md).
|