Files
minecraft-lab/docs/deploy.md
T
2026-10-04 00:30:09 +07:00

172 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SSH deployment — Phase 7
`./mcpack deploy` применяет готовый полный immutable release через SSH/rsync.
Если artifact ещё не создан, команда вызывает clean `build --release`;
если уже есть, проверяет его checksums и provenance. Development artifact
с `git.dirty=true` отклоняется, даже если текущий worktree уже чистый.
## Подготовка цели
На host нужны Linux x86_64, Node.js 22+, доступный Docker daemon, rsync,
GNU tar и zstd. Pinned Compose и небольшой Node agent с закреплённым YAML
parser передаются из локального bootstrap/dependencies; системный Docker
не устанавливается. У оператора должны быть права на весь runtime и его
владельцев; выбранные UID/GID согласовать с владельцем каталога.
В `platform/config.yaml` выбрать SSH host/alias и **отдельный root сборки**:
```yaml
server:
host: crab@192.168.1.61
directory: /home/crab/workspace/minecraft-lab/minecraft-lab-neoforge-spike
memory: 2G
port: 25565
```
Host `.env` готовится отдельно, вне releases, с EULA/UID/GID/memory/port
и стабильным MC_PROJECT_NAME. Runtime startup читает именно этот файл;
build defaults не перезаписывают host settings. Первое применение требует
пустого runtime без старого binding; существующий неопознанный мир не
принимается автоматически. У разных сборок разные roots, projects и ports.
SSH host key должен быть известен заранее. Используются BatchMode,
StrictHostKeyChecking=yes и keepalive. Ключи/порты задать в SSH config;
password-only сессия может использовать заранее аутентифицированный
ControlMaster. Пароль не записывается в config, env, artifact или agent.
```bash
./mcpack deploy --artifact /absolute/full-release
# Порт/ControlMaster/known_hosts в отдельном SSH config:
./mcpack deploy --artifact /absolute/full-release --ssh-config /absolute/ssh-config
# Node из nvm, которого нет в non-interactive SSH PATH:
./mcpack deploy --artifact /absolute/full-release \
--ssh-config /absolute/ssh-config \
--remote-node /home/crab/.nvm/versions/node/v26.10.0/bin/node
```
`--config FILE` выбирает другой platform config. Timeout берётся из его
`deploy.healthcheck_timeout`; он должен быть больше 10 секунд stability.
Первый image/dependency download может требовать 600+ секунд. IPv6 host
и другие сложные адреса сейчас задавать через SSH alias.
## Выполнение и state
Под SSH удерживается одна `.mcpack-runtime.lock` на всё получение релиза,
backup и применение. Перед передачей проверяются незавершённый deployment,
source/binding, target version collision, host settings/права и свободное место.
Релиз передаётся rsync в `releases/.incoming-*`, проверяется на host и
публикуется atomic rename. Сбой передачи не останавливает исходный сервер.
Agent в `.mcpack/agent-UUID/` также проверяется по полной checksum coverage.
Перед применением проверяется каждый replace-managed файл прошлого release.
При изменении/missing file или занятом новом managed path возвращается конфликт.
Для небольших server-owned text configs выводится content diff, для остальных
файлов — expected/actual hash. Неуправляемые файлы не удаляются. Нужно перенести
полезные правки в source и построить новую версию; флага force для молчаливого
перетирания конфигов нет.
Если тот же release уже активен, выполняется `health` без restart; успешный
повторный deploy возвращает noop. Одинаковая версия с другим manifest/checksums
отклоняется до остановки. Если активный release unhealthy, повторный deploy
не перезапускает его автоматически.
При смене релиза исходный сервер останавливается, подтверждается остановка,
создаётся verified snapshot всего runtime и исходного release. Только после
этого apply callback меняет binding, удаляет отсутствующие в новом релизе
известные replace-managed файлы и запускает target. Конфликты проверяются
повторно непосредственно перед apply. Image применяет pack/server overrides
при запуске; runtime-generated/unmanaged данные сохраняются.
После стабильного mc-health/status query обновляются previous-release и
active-release, каждый через atomic rename. Deployment state записывается
перед каждым этапом и связывает source/target identities, прежние pointers,
backup path и факт apply. Пара указателей не является единым filesystem
transaction: interrupted `committing` требует просмотра state перед recovery.
## Ошибка и ручное восстановление
Любой failed/incomplete `deployment-state.json` блокирует следующую операцию.
При прерывании SSH во время upload worker сохраняет failed state и освобождает
lock; при принудительном убийстве worker/power loss lock может остаться.
Не удалять stale lock, пока соответствующий host process действительно жив.
После ошибки **до apply** source/runtime binding не переключаются. При ошибке
backup сервер может остаться остановленным; проверить logs и backup operation.
После подтверждения неизменности мира можно запустить исходный release.
Failed state нужно сохранить для аудита и явно разрешить только после recovery.
Если `applied=false`, binding совпадает с active manifest, причина исправлена
и исходный сервер проверен health, сохранить failed record под отдельным именем
в server root, затем повторить deploy. Для ручного config edit новый clean
release должен содержать ровно текущие bytes этого managed файла — такой
осознанный перенос разрешается. Любое другое содержимое остаётся конфликтом.
Пример архивирования **только после перечисленных проверок на host**:
```bash
mv "$MC_ROOT/deployment-state.json" \
"$MC_ROOT/deployment-state-resolved-$(date -u +%Y%m%dT%H%M%SZ).json"
```
Не применять этот способ к `applied=true`, неизвестному binding или
interrupted committing: сначала восстановить/завершить реальное состояние.
После ошибки **apply/startup** target останавливается, source pointers не
продвигаются, binding остаётся на фактически применённом target и snapshot
сохраняется. Старый pack автоматически не запускается на изменённом мире.
Восстановить snapshot в новый root вместе с сохранённым source release по
[backups.md](backups.md), подготовить host settings, удалить старый контейнер,
запустить восстановленную копию и проверить health. Не менять binding вручную,
чтобы обойти защиту существующего мира.
Для первого неудачного deploy без snapshot использовать state/release/diagnostics:
пустой мир можно повторно инициализировать отдельно либо явно завершить запуск
того же target. При ошибке `committing` сначала проверить actual binding,
Docker health и оба pointer files. Snapshot recovery реализован в
[Phase 8](rollback.md). Простое удаление failed state не является recovery.
## Текущий проверенный host
На `crab@192.168.1.61:2228` подготовлен root
`/home/crab/workspace/minecraft-lab/minecraft-lab-neoforge-spike`.
Release 0.0.5 healthy (обновление публикации порта после Phase 7), UID/GID 1000:1000, memory 2G,
MC_PROJECT_NAME=minecraft-lab-neoforge-spike. Offline mode включён.
Clean release собран в отдельном checkout и опубликован локально:
```bash
./mcpack deploy \
--artifact dist/minecraft-lab-neoforge-spike-0.0.5 \
--ssh-config .tools/phase7-ssh-target/config \
--remote-node /home/crab/.nvm/versions/node/v26.10.0/bin/node
```
SSH config хранит только соединение/known_hosts/ControlPath. После окончания
ControlMaster для password login сначала заново аутентифицировать сессию:
```bash
ssh -F .tools/phase7-ssh-target/config minecraft-lab-target true
```
Host settings теперь содержат `MC_BIND_ADDRESS=0.0.0.0`; порт 25565
публикуется на всех IPv4-интерфейсах host. В Prism подключаться напрямую
к **192.168.1.61:25565**, без SSH tunnel. Локальный Phase 0 сервер остаётся
отдельным на 127.0.0.1:25565. Default для новых host остаётся 127.0.0.1;
LAN bind выбирается явно в host .env. Проверка — [network-results.md](network-results.md).
Сохранённый remote agent содержит `scripts/server.sh`. Для lifecycle на host
выбрать этот agent, задать абсолютные MC_ROOT/MC_RELEASE_DIR, указать nvm Node
в PATH и выполнить wrapper:
```bash
export PATH=/home/crab/.nvm/versions/node/v26.10.0/bin:$PATH
export MC_ROOT=/home/crab/workspace/minecraft-lab/minecraft-lab-neoforge-spike
export MC_RELEASE_DIR="$MC_ROOT/releases/$(cat "$MC_ROOT/active-release")"
# Подставить один из проверенных каталогов .mcpack/agent-*:
/absolute/agent/scripts/server.sh health
/absolute/agent/scripts/server.sh logs --tail 100
```
При failed deployment брать фактически применяемый release из state/binding,
а не автоматически active-release. Agents/releases/backups автоматически
не удаляются. Свидетельства и границы проверок — [phase7-results.md](phase7-results.md).