diff --git a/HISTORY/2026-10-10-session-log.md b/HISTORY/2026-10-10-session-log.md new file mode 100644 index 0000000..80c9c55 --- /dev/null +++ b/HISTORY/2026-10-10-session-log.md @@ -0,0 +1,140 @@ +# История правок shared-sqs — 2026-10-10 (публичная точка на ВМ, TLS, замеры) + +> Запись по требованию «документировать всё, включая собственные ошибки» (приказ 2026-09-24). +> Предыдущие: `HISTORY/2026-10-07-session-log.md`, `doc/thinking/*-2026-10-08.md`. +> Сессия велась двумя моделями: сначала DeepSeek Flash, затем DeepSeek Pro (архитектор) — +> Pro перепроверял выводы Flash, часть из них оказалась неверной (см. раздел 4). + +## 1. Задача + +Вынести публичную точку SQS на ВМ `5.172.178.213` (обход больного managed-шлюза) и +**проверить гипотезу** из `MANUAL-NEXT-2026-10-08.md` (Шаг 1): нет ли на пути +«интернет → ВМ» той же сетевой болезни (зависания ~51 с, таймауты 31–33 с). +Требования владельца по пути: домен — только свой (`sinefo.ru`); `kube5s` из проекта убрать. + +## 2. Хронология (что делалось и что получалось) + +### 2.1. Сборка и запуск на ВМ +- `make build` → `shared-sqs` v0.1.35 (статический, x86_64, 17 МБ). +- `scp` → `naeel@5.172.178.213:~/sqs-test/shared-sqs`. +- Запуск memory-only: `SHARED_SQS_SEED_DEMO=true ./shared-sqs --admin-token=dev-token-123 --port=4100`. +- Локально на ВМ: `/health` → `200 {"status":"ok","version":"v0.1.35"}`; + `ListQueues` без подписи → `403 MissingAuthenticationToken` (корректно). +- ⚠️ Предупреждение `Failure to find default config file` — `goaws.yaml` на ВМ нет, + приложение работает на встроенных дефолтах (см. 5.1). + +### 2.2. Разведка ВМ +- Публичный адрес — `5.172.178.213` (NAT); внутренний `10.10.102.21` (`ens192`), hostname `naeel-vm`. +- Снаружи прилетают только 80/443. Проверка портов: + - `8443` — занят DNAT: `iptables -t nat`: `--dport 8443 -j DNAT --to-destination 95.179.252.111:443` + (сервис `vpn-transit-dnat`, `enabled/active`) → весь трафик на 8443 уходит на Vultr **до** ВМ. + - `8888`/`9443` — `/dev/tcp` показывает «OPEN», но локально **никто не слушает** и HTTP не отвечает + (curl timeout) → это SYN-proxy провайдерского firewall, порты непригодны. +- `/etc/hosts` на ВМ содержит внутренние имена: `gitea.mgmt.nubes.ru`, `sqs.containerk8s.dev.nubes.ru` + → `185.247.187.151`, `tf-registry.containerk8s.services.ngcloud.ru`, `s3.msk-1.ngcloud.ru`. + Резолвер ВМ — публичный (`8.8.8.8`, `1.1.1.1`), поэтому имена `*.services.ngcloud.ru` не резолвятся. + +### 2.3. Блокер nginx (возник 10-08, снят 10-10) +- 10-08: `sudo nginx -t` **падал**: `host not found in upstream "contractor.pythonk8s.services.ngcloud.ru" + in sites-enabled/check.kube5s.ru:44` — внутреннее имя не резолвится. +- 10-10 (после ребута ВМ): конфиг `check.kube5s.ru` оказался **изменён** (catch-all `location /` + на contractor убран, добавлен `location /rf`) → `nginx -t` **проходит**, nginx перезагружаем. +- Следствие: переход к рабочему пути упростился (сначала была построена схема со вторым nginx, см. 2.4). + +### 2.4. Второй nginx на 10443 (сделан, затем убран) +- Владелец пробросил порт: firewall `[22, 80, 443, 4443, 10443]`. +- Проверено: `10443` реально доходит до ВМ (`/health` 200), `4443` — нет. +- Поднят **отдельный** nginx: `/etc/nginx-sqs/nginx.conf`, pid `/run/nginx-sqs.pid`, + `listen 10443` → `proxy_pass http://127.0.0.1:4100`. Запуск `sudo nginx -c /etc/nginx-sqs/nginx.conf`. + +### 2.5. Замеры (гипотеза ПОДТВЕРЖДЕНА) + +| Тест | Инструмент | Результат | +|---|---|---| +| HTTP, 30 запросов 1КБ/10КБ/100КБ/256КБ | `curl --aws-sigv4` | 30/30 **200**, max **0.99 с** | +| HTTPS, 10 запросов 26КБ…260КБ | `curl --aws-sigv4` | 10/10 **200**, 0.7–3.2 с | +| Long-poll `ReceiveMessage` `WaitTimeSeconds=20` | `curl` | **20.3 с, 200** (корректно) | + +Ни зависаний ~51 с, ни таймаутов 31–33 с. **На пути «интернет → ВМ 213» болезни нет.** + +### 2.6. DNS +- `sinefo.ru` делегирован в реестре .ru на `ns3.ngcloud.ru` / `ns4.ngcloud.ru` (проверено через `a.dns.ripn.net`). +- `sqs.sinefo.ru A 5.172.178.213` — публично резолвится. Ранее запись была `185.247.187.83`, + что = **IP самого DNS-сервера** `ns3.ngcloud.ru`, а не ВМ (исправлено владельцем). + +### 2.7. TLS (Let's Encrypt) +- `sudo certbot certonly --webroot -w /var/www/acme -d sqs.sinefo.ru --non-interactive --agree-tos` + (аккаунт LE на ВМ уже существовал → без нового e-mail) → `/etc/letsencrypt/live/sqs.sinefo.ru/`. +- Срок: до 2027-01-08, автопродление настроено. +- ACME-челлендж обслуживается главным nginx (vhost 80 с `location /.well-known/acme-challenge/`). + +### 2.8. Публичная точка (итог) +- Главный nginx, `/etc/nginx/conf.d/sqs-sinefo.conf`: + - **80**: ACME-челлендж + редирект на https; + - **443 ssl**: сертификат `sqs.sinefo.ru` + `proxy_pass http://127.0.0.1:4100`, `Host $http_host`. +- Проверено снаружи: `https://sqs.sinefo.ru/health` → 200 (cert valid), SigV4, 256 КБ за 1.05 с. + +### 2.9. Уборка +- Второй nginx (10443) остановлен, `/etc/nginx-sqs` удалён; порт 10443 свободен. +- `conf.d/sqs-sinefo.conf` — заменён на нормальный vhost (было: HTTP-only левак от 10-08). +- Из **актуального** дока `doc/2026-08-13-migration-to-managed.md` убран `kube5s.ru` + (квинтет: `iot.kube5s.ru`→`iot.nubes.ru`, `qu.kube5s.ru`×3→`sqs.containerk8s.dev.nubes.ru`), + коммит `a47743f`. В `doc/legacy/` (история) не трогал. + +## 3. Грабли (для повторного использования) + +1. **`proxy_set_header Host $host` теряет порт** → SigV4 `SignatureDoesNotMatch`. + Нужен `$http_host`. (nginx `$host` — имя без порта; `$http_host` — заголовок целиком.) +2. **`~/.aws/config [default]` содержит `endpoint_url = https://s3.msk-1.ngcloud.ru`** → + `aws sqs ...` без явного `--endpoint-url` уходит в S3 и получает + `405 MethodNotAllowed` (Ceph RGW, `HostId=...-dc1-msk-1`). **Всегда задавать `--endpoint-url`.** +3. **Креды демо-тенанта рандомны при каждом старте** — брать из `~/sqs-test/sqs.log` + (`seed: создан тенант ... AccessKey=...`). При «address already in use» в логе креды **мёртвого** инстанса. +4. `pkill -f "http.server 10443"` по SSH **самоматчится** на строку ssh-команды и убивает сессию — + использовать `pkill -x <имя>`. +5. Порт `8443` на 213 **нельзя занимать** — там DNAT транзита на Vultr. + +## 4. ОШИБКИ (сводка, включая ошибки Flash) + +| # | Что утверждалось/сделано | Что на самом деле | Исправление | +|---|---|---|---| +| 1 | «При ребуте ВМ nginx не поднимется» (из-за битого upstream) | После ребута nginx `active`, 80/443 слушают | Неверный вывод; снят при перепроверке | +| 2 | «`.83` — мёртвый IP» | `185.247.187.83` = живой DNS `ns3.ngcloud.ru` (порт 53); проверял только 80/443 | Признано при перепроверке | +| 3 | Запуск второго инстанса при живом первом | `fatal: bind: address already in use`; лог перезаписан кредами мёртвого → `InvalidClientTokenId` | `pkill -x shared-sqs`, один инстанс, креды из лога | +| 4 | Второй nginx: `Host $host` | SigV4 `SignatureDoesNotMatch` | `Host $http_host` | +| 5 | Прямые DNS-выводы по регексу `location / ` | Первый `grep` не нашёл (паттерн с пробелом) — чуть не сделал ложный вывод | Перечитал файл целиком (`cat`) | +| 6 | «Только 80/443 открыты» | 8888/9443 «принимают» TCP (SYN-proxy), но пусты | Уточнено: рабочие — только 80/443 | + +## 5. Состояние и воспроизведение + +### 5.1. Итоговое состояние +- **Работает:** `https://sqs.sinefo.ru` (443, TLS) → shared-sqs на ВМ 213 (memory-only, `127.0.0.1:4100`). +- SQS: `~/sqs-test/shared-sqs`, лог `~/sqs-test/sqs.log`, pid меняется. Демо-тенант + 5 очередей. +- **Дефект:** `QueueUrl` в ответах = `http://region.host:port//` — реального хоста нет + (следствие отсутствия `goaws.yaml`). Клиенты **с** `endpoint_url` не страдают (берут только путь), + клиенты **без** него — сломаны. См. открытый вопрос 6.1. + +### 5.2. Как поднять заново +```bash +# на ВМ 213 +cd ~/sqs-test && setsid nohup env SHARED_SQS_SEED_DEMO=true \ + ./shared-sqs --admin-token=dev-token-123 --port=4100 --loglevel=info > sqs.log 2>&1 Текущее состояние и конфигурация. Хронология и ошибки — в `HISTORY/2026-10-10-session-log.md`. +> Проверено снаружи: `https://sqs.sinefo.ru/health` → 200. + +## 1. Схема + +``` +клиент (AWS SDK, SigV4) + │ https://sqs.sinefo.ru (443, TLS Let's Encrypt) + ▼ +[ ВМ 213: главный nginx ] conf.d/sqs-sinefo.conf + │ proxy_pass http://127.0.0.1:4100 ; Host $http_host + ▼ +[ shared-sqs ] ~/sqs-test/shared-sqs (Go, memory-only) +``` + +ВМ: публичный `5.172.178.213` (NAT), внутренний `10.10.102.21`, hostname `naeel-vm`. + +## 2. Файлы + +| Что | Где | +|---|---| +| Vhost nginx (80 ACME+редирект, 443 TLS) | `/etc/nginx/conf.d/sqs-sinefo.conf` (ВМ) | +| Сертификат | `/etc/letsencrypt/live/sqs.sinefo.ru/{fullchain,privkey}.pem` | +| ACME-webroot | `/var/www/acme/.well-known/acme-challenge/` | +| Бинарник/лог/креды | `~/sqs-test/shared-sqs`, `~/sqs-test/sqs.log` | +| Бэкапы nginx | `/etc/nginx/conf.d.bak-*` | + +## 3. Конфиг vhost (эталон) + +```nginx +server { + listen 80; + server_name sqs.sinefo.ru; + location /.well-known/acme-challenge/ { root /var/www/acme; } + location / { return 301 https://$host$request_uri; } +} +server { + listen 443 ssl; + server_name sqs.sinefo.ru; + ssl_certificate /etc/letsencrypt/live/sqs.sinefo.ru/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/sqs.sinefo.ru/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + + client_max_body_size 10m; + proxy_request_buffering off; + location / { + proxy_pass http://127.0.0.1:4100; + proxy_http_version 1.1; + proxy_set_header Host $http_host; # ВАЖНО: не $host — иначе SigV4 не сойдётся + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_read_timeout 120s; + proxy_send_timeout 120s; + } +} +``` + +## 4. Критичные условия (иначе не работает) + +1. **`Host $http_host`** — SigV4 подписывает заголовок `Host` целиком (с портом). + `$host` порт отбрасывает → `SignatureDoesNotMatch`. Сервис берёт хост из запроса: + `app/auth/auth_middleware.go:315-317`. +2. **DNS:** `sqs.sinefo.ru A 5.172.178.213`; делегирование `sinefo.ru` → `ns3/ns4.ngcloud.ru`. + Сертификат выдаётся только когда домен резолвится (HTTP-01 через главный nginx, порт 80). +3. **Порт 8443 на 213 занят** DNAT-ом транзита (`→ 95.179.252.111:443`) — не использовать. +4. Проксирование тел — `proxy_request_buffering off`; лимит SQS 256 КБ. + +## 5. Замеры (2026-10-10) — болезнь managed-шлюза НЕ воспроизводится + +- HTTP 30× (1КБ–256КБ): 30/30 200, max 0.99 с. +- HTTPS 10× (26КБ–260КБ): 10/10 200, 0.7–3.2 с. +- Long-poll `WaitTimeSeconds=20` → 20.3 с, 200. + +Гипотеза мануала (Шаг 1) подтверждена: 0 зависаний ~51 с, 0 таймаутов 31–33 с. + +## 6. Управление + +```bash +# запуск SQS на ВМ +cd ~/sqs-test && setsid nohup env SHARED_SQS_SEED_DEMO=true \ + ./shared-sqs --admin-token=dev-token-123 --port=4100 --loglevel=info > sqs.log 2>&1 /` (плейсхолдеры — нет `goaws.yaml`). +Причина: `app/gosqs/tenant_helpers.go:29-37` (схема `http://`, формат `{region}.{host}:{port}`; +Host/Port/Region только из `app/conf/goaws.yaml`, env-переменных нет). Клиенты с `endpoint_url` +не страдают (используют путь), клиенты без него — сломаны.