Files
han-app/codebase/backend/deployment/RUNBOOK.ru.md
T

17 KiB
Raw Blame History

Инструкция по развертыванию HAN Chat в production-like окружении

Это исполняемый чек-лист для контура на одной виртуальной машине. PostgreSQL и S3 используются как внешние управляемые сервисы. Во время развертывания запрещено использовать docker compose down -v, откат миграций Alembic и изменяемые теги образов.

Подробная пошаговая инструкция для первого запуска находится в deployment/DEPLOYMENT_GUIDE.ru.md.

Этап 0 — решения и зоны ответственности

  • Зафиксированы SHA/дайджесты релиза, окно обслуживания, дежурный и ответственный за откат.
  • Согласованы RPO/RTO; начальные цели: RPO PostgreSQL не более 15 минут и RTO не более 4 часов.
  • Выбран удаленный OTLP-бэкенд либо принято ограничение на использование только отладочного контура.
  • Явно приняты риски mock OTP, заглушки Safety и заглушки bitrix-sync.

Этап 1 — VPC, DNS и группы безопасности

  • Управляемый PostgreSQL имеет только приватную точку доступа и принимает трафик от группы безопасности VM.
  • Из интернета доступны только TCP-порты VM 80/443; SSH ограничен VPN или CIDR администраторов.
  • Порты 6379, 4317/4318, 8000, 8080 и 9000 закрыты для внешнего доступа.
  • DNS-запись A для PUBLIC_HOST указывает на VM; исходящий HTTPS доступен.

Этап 2 — защита виртуальной машины

На новой Ubuntu 24.04 можно выполнить подготовительный скрипт:

sudo deployment/scripts/setup-vm.sh

Перед включением HARDEN_SSH=true обязательно проверьте вход по ключу в отдельной SSH-сессии. Параметры запуска и безопасные значения по умолчанию описаны в начале скрипта.

  • Установлена Ubuntu 24.04; работают NTP, автоматические обновления безопасности и оповещения о заполнении диска.
  • Вход учетной записью развертывания по ключу проверен во второй сессии; вход root и SSH по паролю отключены.
  • Правила UFW/облачной группы безопасности и политика DOCKER-USER сохраняются после перезагрузки.
  • Docker Engine и Compose поддерживают include и полную форму env_file.

Этап 3 — управляемый PostgreSQL

  • Включены ежедневные резервные копии, PITR, защита от удаления, шифрование и оповещения.
  • CA-сертификат провайдера установлен по пути PG_CA_HOST_PATH; все DSN используют verify-full.
  • Для схем han_app, bitrix_local, bitrix_sync, message_safety, keycloak созданы отдельные роли миграций и выполнения; запрет лишних прав проверен тестами.
  • Миграции проверены на пустой БД и на клоне БД предыдущего релиза.

Этап 4 — Selectel S3

  • Бакеты карантина, вложений и документов закрыты от публичного доступа и зашифрованы.
  • Права API ограничены префиксами; учетные данные Safety имеют доступ к карантину только на чтение.
  • CORS бакетов разрешает только точный HTTPS-origin браузера и необходимые заголовки PUT.
  • Срок хранения карантина превышает время Safety polling/recovery; политика хранения данных согласована.

Этап 5 — неизменяемый релиз

  • Репозиторий переключен на утвержденный SHA в detached-режиме; рабочее дерево чистое.
  • Образы сервисов неизменяемы и просканированы; нерешенных критических и высоких уязвимостей нет.
  • Корневой docker-compose.yml является единственной точкой запуска.

Этап 6 — окружение и секреты

umask 077
cp .env.example .env
chmod 600 .env
# Замените заглушки через защищенный редактор или менеджер секретов.
./scripts/validate-env .env
docker compose --env-file .env config --quiet
  • Парные токены совпадают, PostgreSQL проверяет TLS, публичные URL используют HTTPS.
  • Риск mock OTP принят; все секреты уникальны и содержат не менее 128 бит энтропии.
  • Установлено FRONTEND_DEV_PROXY_ENABLED=false; таймауты Safety и nginx согласованы.

Этап 7 — образы и статический frontend

docker compose --env-file .env pull
docker compose --env-file .env build --pull frontend-static nginx redis
docker compose --env-file .env run --rm frontend-static
  • Экспорт frontend проверен и просканирован, затем скопирован сервисом frontend-static в именованный volume.
  • Артефакты сборки не содержат секретов и непредусмотренных source map.
  • На диске VM остается не менее 30% свободного места.

Этап 8 — топология

docker compose --env-file .env config --services
python3 -m unittest discover -s tests -v
  • Только nginx публикует 80:80 и 443:443; сервиса PostgreSQL в Compose нет.
  • Присутствуют volumes Redis AOF/RDB/ACL и постоянной очереди OTEL.
  • Сети backend и observability являются внутренними.

Этап 9 — первоначальная настройка ACME/TLS

Установите NGINX_TLS_ENABLED=false только для команды первоначального запуска:

NGINX_TLS_ENABLED=false docker compose --env-file .env up -d nginx
docker compose --profile certbot run --rm certbot certonly \
  --webroot -w /var/www/certbot -d "$PUBLIC_HOST" \
  --cert-name "$PUBLIC_HOST" --email "$ACME_EMAIL" \
  --agree-tos --no-eff-email --non-interactive
docker compose --env-file .env up -d --force-recreate nginx
docker compose exec -T nginx nginx -t -c /tmp/nginx.conf

Сначала выполните проверку с параметром Certbot --staging. Установите systemd-таймер, запускающий deployment/scripts/ssl-renew.sh дважды в сутки, и проверьте certbot renew --dry-run. Включайте HSTS только после проверки цепочки сертификатов, имени хоста, перенаправления и поддержки TLS 1.2/1.3.

Этап 10 — миграции и начальные данные

Создайте у провайдера точку восстановления PITR, затем выполните:

PITR_MARKER_CONFIRMED=true deployment/scripts/migrate.sh
deployment/scripts/seed.sh
  • Активны ожидаемые ревизии Alembic; runtime-пользователи не выполняли DDL.
  • Повторный seed завершается успешно; обязательные настройки не содержат секретов.
  • Схема остается обратно совместимой с образами предыдущего релиза.

Этап 11 — Keycloak

docker compose up -d keycloak
docker compose ps keycloak
  • Issuer discovery/JWKS точно совпадает с публичным HTTPS URL /auth.
  • Frontend-клиент является публичным PKCE S256; implicit, password и social flows отключены.
  • Неверный или повторно использованный OTP и превышение лимитов безопасно отклоняются; settings bridge работает fail-closed.
  • При KEYCLOAK_YANDEX_CAPTCHA_ENABLED=true initial send и resend требуют свежий SmartCaptcha token; техническая недоступность Yandex подтверждена как fail-open в логах.
  • CSP login-страницы содержит smartcaptcha.cloud.yandex.ru/yastatic.net, а /auth/realms/master/protocol/openid-connect/3p-cookies/step2.html и Admin Console работают без CAPTCHA CSP.
  • Временный администратор удален либо его пароль изменен; для именного администратора включена MFA.

Если предыдущая попытка сохранила custom CSP в realm, сбросьте только это поле через kcadm; .env как shell-файл не загружать:

docker compose exec -T keycloak sh -lc '
set -eu
cfg=/tmp/han-kcadm.config
/opt/keycloak/bin/kcadm.sh config credentials --config "$cfg" \
  --server http://127.0.0.1:8080/auth --realm master \
  --user "$KC_BOOTSTRAP_ADMIN_USERNAME" \
  --password "$KC_BOOTSTRAP_ADMIN_PASSWORD"
/opt/keycloak/bin/kcadm.sh update realms/han-chat --config "$cfg" \
  -s "browserSecurityHeaders.contentSecurityPolicy="
rm -f "$cfg"
'

Этап 12 — последовательный запуск и готовность

docker compose up -d redis
docker compose up -d keycloak otel-collector
docker compose up -d message-safety
docker compose up -d api-backend
docker compose up -d bitrix-local-app bitrix-sync
docker compose up -d nginx
docker compose ps
  • Нет циклических перезапусков и OOM; критические readiness-проверки успешны.
  • Сохраняется только документированная деградация: Bitrix не установлен и bitrix-sync работает как заглушка.
  • Внешний запрос /internal/* возвращает 404; OTEL принимает телеметрию.

Этап 13 — Bitrix24

  • URL установки, обработчика и placement используют точные публичные HTTPS-пути.
  • Коннектор han_mobile_app активен в Открытой линии 8; события привязаны однократно.
  • OAuth зашифрован; callback-, application- и service-токены не попадают в логи.
  • Исходящие сообщения и ответы оператора идемпотентны; внутренний статус не опубликован наружу.

Этап 14 — smoke- и E2E-тесты

deployment/scripts/smoke.sh
  • Успешны сценарии гостя, OTP/PKCE/bootstrap/session, обновления токена и выхода.
  • Проверены Safety allow/deny/pending/timeout и один параллельный медленный poll.
  • Проверены карантин, перенос и удаление файлов, скачивание только владельцем и аудит.
  • Проверены переподключение WS с REST-сверкой, 404 при обращении к чужому ресурсу, идемпотентность и 429.
  • Логи не содержат PII, текстов сообщений, токенов и query-параметров presigned URL.

Этап 15 — наблюдаемость

  • Известный request ID связывает трассировку nginx, API и downstream-сервисов; UX ID не используется как label.
  • Все три сигнала поступают в выбранный бэкенд; SLO-запросы и оповещения проверены.
  • При недоступности удаленного сервиса ограниченная постоянная очередь заполняется и опустошается без остановки бизнес-функций.
  • Тестовые секреты и PII отсутствуют; проверены метрики перезапуска, потерь, отказов и очереди Collector.

Только для локальной приемки запустите отладочный Collector с удалением чувствительных данных: docker compose --profile observability-local up -d otel-collector-local.

Этап 16 — открытие трафика

  • Этапы 0–15 подписаны; имеются свежие подтверждения backup/PITR и предыдущие образы.
  • HSTS включен; дайджесты релиза, версии схем и realm зафиксированы.
  • Активных инцидентов нет; дежурный и владелец продукта приняли ограничения заглушек.
  • В течение 60 минут контролируются 5xx, auth, доставка, БД, Redis, OOM, очередь OTEL и Bitrix.

Резервное копирование и восстановление

Основным механизмом являются backup/PITR провайдера. Дополнительный проверенный логический дамп:

PG_BACKUP_DSN='postgresql://...?...sslmode=verify-full&sslrootcert=...' \
  deployment/scripts/backup.sh /opt/han-chat/backups

Ежеквартально восстанавливайте PostgreSQL и S3 в изолированной VPC, развертывайте те же дайджесты образов, не направляйте туда production DNS и callbacks Bitrix, выполняйте smoke-тесты и фиксируйте фактические RPO/RTO. Redis можно восстановить пустым: его AOF/RDB не является резервной копией бизнес-данных.

Откат

Откатывайтесь только на образы, совместимые с текущей схемой:

SCHEMA_BACKWARD_COMPATIBLE_CONFIRMED=true \
  deployment/scripts/rollback.sh /secure/path/previous-release.env
ENV_FILE=/secure/path/previous-release.env deployment/scripts/smoke.sh

Дополнение: rollout реальной SMS-авторизации

Текущий runbook остаётся mock-only, пока артефакты module-11 не реализованы. Для SMS release обязательны: schema/role sms, migrations/seed active approved auth_otp, sms-service/worker, exact callback route, парные service tokens, Direct TOKEN_1, согласованные sender/template, отдельные callback credentials, подтверждённый callback source IP и статический egress IP worker.

Порядок: App DB OTP seed → SMS schema/migrations/seed → test с mock Direct → production SMS deploy при KEYCLOAK_OTP_MOCK_ENABLED=true → Keycloak expand migration/SPI → provider smoke и callback/redaction evidence → real mode. Rollback: вернуть mock, не удалять journal/schema, остановить новые real orders и зафиксировать in-flight/uncertain; downgrade только при доказанной совместимости.

Никогда не выполняйте downgrade Alembic. После обратно несовместимой миграции используйте исправление вперед либо согласованный PITR с восстановлением S3 и сверкой Bitrix во время технического обслуживания. Всегда проверяйте outbox, inbox и recovery, чтобы сообщение с неопределенным статусом не было отправлено повторно.