# module-10-vm1. Production deployment ВМ1 > Канонический исполняемый fresh-VM runbook: > [`RUNBOOK.production.ru.md`](../codebase/backend/deployment/RUNBOOK.production.ru.md). > Общие security/deployment контракты: > [`arch-06-service-hosting-security.md`](../../architectory/arch-06-service-hosting-security.md) > и [`arch-10-deployment.md`](../../architectory/arch-10-deployment.md). > ВМ2: > [`module-10-deployment-vm2.md`](../../VM2_services/documentation/module-10-deployment-vm2.md). ## Граница документа Этот модуль фиксирует только связь спецификаций и cutover boundary. Команды bootstrap, release activation, secrets, TLS, migrations, systemd, smoke, reboot, rollback и DR находятся только в production runbook. Production ВМ1 разворачивается на fresh Ubuntu 24.04. In-place hardening legacy single-VM/stub инсталляции запрещён. Legacy `deployment/DEPLOYMENT_GUIDE.ru.md`, `RUNBOOK.ru.md` и `RUNBOOK.md` являются только указателями. ## Host deployment contract - разные Ed25519 keys для `deploy` и break-glass `admin`, не совпадающие с root bootstrap key; - `deploy` не входит в `docker`, `sudo`, `lxd`, `adm`, `systemd-journal`; пишет только в `/var/lib/han-deploy/incoming`; - active release, Compose, `.env`, scripts/helpers, units, secret mappings, credentials и sudoers принадлежат root; - activation проверяет approved SHA-256, project root, absolute/`..` paths, symlink/hardlink и executable modes; - lifecycle — `han-secrets@production.service` и `han-stack@production.service` через exact sudoers; - public TLS копируется root hook из `/etc/letsencrypt` в `/var/lib/han-chat/public-tls`; nginx не получает дерево Certbot; - published Docker ports фильтруются по original destination `conntrack --ctorigdstport 80/443`, включая restart/reboot gates. ## Cutover ВМ1 → ВМ2 ВМ1 владеет public guest/API/auth/SMS/Bitrix local-app ingress `80/443`. ВМ2 владеет Message Safety v2 на private HTTPS `:8443` и CRM sync public webhooks собственного host. Compose, IAM principal и secret bundle между VM не разделяются. До переключения caller на ВМ2: 1. ВМ2 закрыла TLS SAN/CA, PG migrations, Safety capabilities, S3 read-only, performance, egress и rollback gates своего runbook. 2. ВМ1 использует `MESSAGE_SAFETY_URL=https://:8443` и root-owned `MESSAGE_SAFETY_CA_HOST_PATH`. Значение `` определяется внутренним DNS-доменом окружения и задаётся в `.env`; фиксированное каноническое имя не требуется. 3. Internal CA читается фактическим UID API и не читается посторонним UID. 4. Service token paired, private route/SG разрешают `8443` только от ВМ1/ops. 5. Local `message-safety`, Redis DB2, local Safety rules env и stub fallback отсутствуют в production Compose/validator. 6. Caller smoke подтверждает allow/deny/pending/timeout, file flow и fail-closed поведение; status `stub` не принимается. 7. После cutover фиксируются release/image digests, schema/config versions, firewall counters, traces и rollback approval. Rollback caller переключает только на предыдущий schema-compatible immutable release ВМ1. Уже созданные tasks ВМ2 не down-migrate. Потеря ВМ2 не разрешает fail-open или возврат local stub. Bitrix sync cutover выполняется отдельно по runbook ВМ2 после expand migrations `han_app` на ВМ1. CRM webhook ВМ2 не маршрутизируется через nginx ВМ1. ## Связанные модули - API caller и Safety v2: [`module-01-api-backend.md`](module-01-api-backend.md). - Public edge: [`module-03-nginx-vm1.md`](module-03-nginx-vm1.md). - Redis DB0/DB1 и удаление legacy DB2: [`module-04-redis-vm1.md`](module-04-redis-vm1.md). - Keycloak: [`module-08-keycloak.md`](module-08-keycloak.md). - Observability: [`module-09-observability-vm1.md`](module-09-observability-vm1.md). - SMS cutover: [`module-11-idgtl-sms.md`](module-11-idgtl-sms.md).