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

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
+23 -12
View File
@@ -40,7 +40,8 @@ Upstream failures не перенаправляются на другой сер
## 3. HTTP/HTTPS и TLS
- public host каждой VM на `:80` обслуживает только ACME challenge и `308 https://$host$request_uri`, кроме явно зафиксированных исключений профильной спецификации;
- public host каждой VM на `:80` обслуживает только ACME challenge и `308 https://$host$request_uri`;
- единственное route-specific исключение: exact CRM webhook ВМ2 по HTTP возвращает `404/426` без redirect, чтобы query token не отражался в `Location`;
- выделенный API host, если появится, не имеет listener `:80`;
- `:443 ssl http2`, TLS 1.2/1.3, современные cipher suites, session tickets по ops policy;
- сертификат доверенного CA, private key read-only и недоступен приложению;
@@ -53,24 +54,33 @@ Upstream failures не перенаправляются на другой сер
## 4. ACME lifecycle
Выбран webroot Certbot/ACME client с общими named volumes:
Выбран webroot Certbot/ACME client с host-каталогами:
```text
nginx-certs -> /etc/letsencrypt (rw у certbot, ro у nginx)
nginx-acme-webroot -> /var/www/certbot
/etc/letsencrypt root-only ACME state; rw только у root/ACME client
/var/lib/han-chat/public-tls staged fullchain.pem/privkey.pem; ro bind в nginx
/var/lib/han-chat/acme webroot; bind в nginx и ACME client
```
Каждая VM выпускает **свой** сертификат на свой public host. Секреты и volumes двух projects не общие.
Named volume для public certificate/key запрещён. Non-root nginx никогда не
монтирует `/etc/letsencrypt`: после успешного issuance/renewal root hook
проверяет certificate/key и атомарно копирует только нужные PEM в
`/var/lib/han-chat/public-tls` с `root:<dedicated-tls-group>`, directory `0750`
и files `0640`. Каждая VM выпускает **свой** сертификат на свой public host;
host-каталоги двух VM не общие.
Bootstrap:
1. DNS указывает на VM; 80/443 разрешены.
2. Запустить временный HTTP config с `/.well-known/acme-challenge/`.
3. Выпустить certificate без остановки nginx.
4. Проверить `nginx -t`, атомарно активировать TLS config, reload.
2. Подготовить root-owned webroot `/var/lib/han-chat/acme` и временный HTTP config с `/.well-known/acme-challenge/`.
3. Выпустить certificate в root-only `/etc/letsencrypt` без остановки nginx.
4. Проверить certificate/key, атомарно обновить `/var/lib/han-chat/public-tls`, выполнить `nginx -t`, активировать TLS config и reload.
Renew container/host timer выполняет `certbot renew` минимум дважды в сутки;
после фактического renewal проверяет рабочую конфигурацию командой
Root-owned host timer выполняет `certbot renew` минимум дважды в сутки; ACME
client может быть контейнеризован, но только он получает rw bind
`/etc/letsencrypt`, а public certificate остаётся host bind, не named volume.
После фактического renewal hook проверяет пару certificate/key, атомарно
обновляет staging и проверяет рабочую конфигурацию командой
`docker compose exec -T nginx nginx -t -c /tmp/nginx.conf` и отправляет
master-процессу `docker compose kill -s HUP nginx`. Bare-команды `nginx -t` и
`nginx -s reload` запрещены: контейнер read-only, а рабочие config/PID находятся
@@ -82,7 +92,8 @@ success path считается дефектом интеграции с Certbot
Контролируются expiry days и последняя успешная попытка. Staging CA используется
в rehearsal, чтобы не исчерпать лимиты.
Non-root nginx не монтирует root-only дерево Let's Encrypt целиком: только необходимые cert/key files по arch-03/arch-06.
Non-root nginx получает только read-only staging
`/var/lib/han-chat/public-tls`; root-only `/etc/letsencrypt` ему недоступен.
## 5. Request ID и forwarded headers
@@ -176,7 +187,7 @@ nginx/
## 11. Docker Compose
`nginx` подключён к `public` и `backend` (или эквивалентным сетям своей VM). Публикация host ports разрешена только nginx. Filesystem read-only, tmpfs для cache/run/temp/`/etc/nginx/conf.d` по arch-03, non-root где позволяет bind ports/capabilities. Cert volumes read-only для nginx. ACME client имеет только необходимые volumes/network.
`nginx` подключён к `public` и `backend` (или эквивалентным сетям своей VM). Публикация host ports разрешена только nginx. Filesystem read-only, tmpfs для cache/run/temp/`/etc/nginx/conf.d` по arch-03, non-root где позволяет bind ports/capabilities. Host staging public TLS и ACME webroot монтируются с минимальными правами; named volume сертификатов запрещён. ACME client имеет только необходимые bind mounts/network.
Non-root nginx получает writable tmpfs только для `/etc/nginx/conf.d`, `/var/cache/nginx`, `/var/run` и `/tmp`; tmpfs задаёт явные UID/GID/mode. Основной `nginx.conf` подключает конкретный rendered include, не неограниченный wildcard, который позволил бы обойти `nginx -t`.