Реализация на отдельных двух машинах с протестированным взаимодействием по проверке сообщений

This commit is contained in:
mi
2026-08-19 18:24:00 +03:00
parent bbef7a30c9
commit c7a80e7256
103 changed files with 3457 additions and 3725 deletions
+21 -34
View File
@@ -22,8 +22,8 @@
6. S3 — внешний Selectel-compatible storage; клиент получает только presigned URL.
7. Секреты не коммитятся, не вставляются в команды shell history и не выводятся в отчёты.
8. Миграции выполняются отдельными one-shot steps до новой версии приложения.
9. Message Safety запускается как documented stub до замены; это не production antivirus/moderation.
10. `bitrix-sync` вводится только после выполнения preflight/cutover gates module-07; до этого `BITRIX_SYNC_ENABLED=false`, public webhook закрыт на edge.
9. Production Message Safety работает только на ВМ2; local stub/fallback на ВМ1 запрещён. Caller ВМ1 использует private HTTPS, service token и проверку internal CA, при недоступности — fail closed.
10. `bitrix-sync` работает только на ВМ2 и вводится после preflight/cutover gates module-07; до подтверждённого cutover public webhook остаётся закрыт на edge.
11. На ВМ1 и ВМ2 отдельные root Compose projects/systemd units; deploy/rollback выполняются независимо.
12. ВМ2 — самостоятельная service VM с минимальным public webhook ingress, allow-listed egress, отдельным IAM principal и service-specific secret files.
13. OS-роли, SSH/sudo, secrets delivery, container hardening и private-VM lockdown подчиняются arch-06.
@@ -49,7 +49,7 @@
<VM_PRIVATE_IP> приватный IPv4 VM
<VPC_CIDR> например 10.20.0.0/24
<PG_PRIVATE_HOST> private FQDN/IP managed PG
<PG_PORT> 5432 или 6432
<PG_PORT> 5433 для Selectel PgBouncer; иной порт — только фактическое значение другого provider/endpoint
<PG_DATABASE> han_chat
<BACKEND_REPO_URL> URL репозитория этой VM
<BACKEND_ROOT> /opt/han-chat/backend
@@ -115,7 +115,7 @@ DNS: `A <PUBLIC_HOST> → <VM1_PUBLIC_IP>`, `A <PROCESSING_PUBLIC_HOST> → <VM2
## 5. Stage 2 — hardening Ubuntu
Процедура первичная для **каждой** application VM. Скрипт-прототип [`../../HAN_chat/deploy/setup-vm-han-chat.sh`](../../HAN_chat/deploy/setup-vm-han-chat.sh) полезен для UFW, fail2ban, Docker и `DOCKER-USER`. Перед production: review версии; не передавать IP/ключи в git; проверить unattended upgrades; `deploy` не в группе `docker`; `AllowTcpForwarding no` по умолчанию; отдельный `tunnel` при необходимости; root-owned systemd-units и `/etc/sudoers.d/deploy` без wildcard.
Процедура первичная для **каждой** application VM и выполняется только по её профильному production runbook. Перед production: review версии; не передавать IP/ключи в git; проверить unattended upgrades; `deploy` не в группе `docker`; `AllowTcpForwarding no` по умолчанию; отдельный `tunnel` при необходимости; root-owned systemd-units и `/etc/sudoers.d/deploy` без wildcard.
`PUBLIC_DOCKER_PORTS` задаёт профильный runbook (ВМ1: `80,443`; ВМ2 — свои public 80/443, private 8443 не internet).
@@ -216,37 +216,24 @@ Validation: нет `change-me`, paired tokens equal, PG TLS, public HTTPS, `FRON
## 9. TLS/ACME процедура
Webroot two-phase, независимо в root Compose каждой VM, без `compose down`. Staging CA rehearsal, затем production `--cert-name` текущего host. Сертификат и ACME volume между VM не разделяются.
Канонические bootstrap, renewal, validation и safe reload задаёт
[`arch-08-nginx.md`](arch-08-nginx.md). Rollout каждой VM применяет эту модель
независимо, без `compose down` и без named volume сертификатов:
Renew: systemd timer дважды в сутки. Скрипт `<BACKEND_ROOT>/deploy/ssl-renew.sh`:
- root-only ACME state: `/etc/letsencrypt`;
- read-only для nginx host staging: `/var/lib/han-chat/public-tls`;
- host ACME webroot: `/var/lib/han-chat/acme`;
- root-owned systemd timer/hook дважды в сутки с `flock`; пользователь `deploy`
может запускать только утверждённый unit и не получает доступ к ACME state;
- staging CA rehearsal предшествует production issuance; после renewal root
hook проверяет certificate/key, атомарно обновляет staging, выполняет
container `nginx -t` и только затем HUP;
- success path возвращает `0` с пустым stderr; ошибка сохраняет действующий
certificate/config и поднимает alert (<21 дней, page <7 дней).
1. взять `flock`;
2. `docker compose --profile certbot run --rm certbot renew --webroot -w /var/www/certbot --quiet`;
3. при обновлении проверить `docker compose exec -T nginx nginx -t -c /tmp/nginx.conf`;
4. только после успеха `docker compose kill -s HUP nginx`;
5. записать результат и метрику expiry;
6. ненулевой exit при ошибке;
7. не удалять действующий сертификат;
8. success path — `0` и пустой stderr.
Пример unit `/etc/systemd/system/han-chat-cert-renew.service`:
```ini
[Unit]
Description=Renew HAN Chat Let's Encrypt certificate
Requires=docker.service
After=docker.service network-online.target
[Service]
Type=oneshot
User=deploy
WorkingDirectory=<BACKEND_ROOT>
ExecStart=<BACKEND_ROOT>/deploy/ssl-renew.sh
```
Timer `OnCalendar=*-*-* 03,15:20:00`, `RandomizedDelaySec=30m`, `Persistent=true`. `enable --now`, `list-timers`, `certbot renew --dry-run`. Alert <21 дней, page <7 дней. Ошибка renew не останавливает nginx.
Staging issuance, затем production `--cert-name` текущего host. Host для ВМ1 — `<PUBLIC_HOST>`; для ВМ2 — `<PROCESSING_PUBLIC_HOST>`; private `8443` — internal CA, не Let's Encrypt. Сертификат и ACME volume между VM не разделяются.
Host ВМ1 — `<PUBLIC_HOST>`, ВМ2 — `<PROCESSING_PUBLIC_HOST>`; private `8443`
использует internal CA, не Let's Encrypt. Ни ACME state, ни staging между VM не
разделяются.
## 10. Сквозной порядок startup и cutover
@@ -337,4 +324,4 @@ DR потеря VM: новая Ubuntu в VPC, hardening, DNS, secrets из vault
- ВМ1: [`module-10-deployment-vm1.md`](../VM1_app/documentation/module-10-deployment-vm1.md).
- ВМ2: [`module-10-deployment-vm2.md`](../VM2_services/documentation/module-10-deployment-vm2.md).
- Прототипы: [`../../HAN_chat/Deploy_steps.md`](../../HAN_chat/Deploy_steps.md), [`../../HAN_chat/deploy/setup-vm-han-chat.sh`](../../HAN_chat/deploy/setup-vm-han-chat.sh), [`../../HAN_chat/deploy/init-managed-postgres.py`](../../HAN_chat/deploy/init-managed-postgres.py).
- Исполняемые процедуры: [`RUNBOOK.production.ru.md`](../VM1_app/codebase/backend/deployment/RUNBOOK.production.ru.md) для ВМ1 и [`RUNBOOK.ru.md`](../VM2_services/codebase/services/deployment/RUNBOOK.ru.md) для ВМ2.