144 lines
8.2 KiB
Markdown
144 lines
8.2 KiB
Markdown
# Публичная точка SQS на ВМ 213 — как устроено (справочник, 2026-10-10)
|
||
|
||
> Текущее состояние и конфигурация. Хронология и ошибки — в `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 </dev/null &
|
||
# креды демо-тенанта
|
||
grep "seed: создан тенант" ~/sqs-test/sqs.log | tail -1
|
||
# проверка
|
||
curl -sS https://sqs.sinefo.ru/health
|
||
```
|
||
|
||
## 7. QueueUrl — ИСПРАВЛЕНО (2026-10-10)
|
||
|
||
**Было:** `QueueUrl` = `http://region.host:port/<tenantID>/<queue>` (плейсхолдеры — на ВМ нет `goaws.yaml`).
|
||
|
||
**Стало:** база URL задаётся через `ExternalURLBase` (config `goaws.yaml` **или** env
|
||
`SHARED_SQS_EXTERNAL_URL_BASE`). На ВМ запускается с `SHARED_SQS_EXTERNAL_URL_BASE=https://sqs.sinefo.ru` →
|
||
`QueueUrl` = `https://sqs.sinefo.ru/<tenantID>/<queue>` (проверено снаружи).
|
||
|
||
Изменения (коммиты `469132b`, `ca0372b`):
|
||
- `app/models/configuration.go` — поле `Environment.ExternalURLBase`;
|
||
- `app/gosqs/tenant_helpers.go` — `tenantQueueURL` учитывает `ExternalURLBase`; добавлена
|
||
экспортированная `TenantQueueURL`;
|
||
- `app/conf/config.go` — env-override `SHARED_SQS_EXTERNAL_URL_BASE` в `applyEnvironmentDefaults`
|
||
(срабатывает и при отсутствии `goaws.yaml` — важная тонкость: `LoadYamlConfig` делает ранний
|
||
`return` без конфига, поэтому override там не срабатывал);
|
||
- `app/cmd/seed.go` — демо-очереди формируют URL через `gosqs.TenantQueueURL` (убрано
|
||
дублирование логики — оно и было причиной, что фикс «не применялся»);
|
||
- тест `app/gosqs/tenant_helpers_test.go`.
|
||
|
||
## 8. Устойчивость: systemd + локальный Redis (2026-10-10)
|
||
|
||
- **Redis** установлен на 213 (`apt install redis-server` 7.0.15), слушает `127.0.0.1:6379`,
|
||
включён **AOF** (`/etc/redis/redis.conf`: `appendonly yes`) — состояние переживает рестарт.
|
||
- **systemd-юнит** `/etc/systemd/system/shared-sqs.service`: `Restart=always`, `RestartSec=2`,
|
||
`WantedBy=multi-user.target` (автостарт при ребуте), `Requires=redis-server.service`,
|
||
`User=naeel`, `WorkingDirectory=/home/naeel/sqs-test`, `StandardOutput=append:.../sqs.log`.
|
||
- **env** `/etc/shared-sqs.env` (600, root): `SHARED_SQS_ADMIN_TOKEN`, `SHARED_SQS_SEED_DEMO`,
|
||
`SHARED_SQS_EXTERNAL_URL_BASE=https://sqs.sinefo.ru`, `REDIS_ADDR=127.0.0.1:6379`.
|
||
- Управление: `sudo systemctl {status,restart,stop,start} shared-sqs`.
|
||
|
||
**Закрыто:** крах процесса (авторестарт) и ребут ВМ (автостарт + Redis с диска из AOF; проверено —
|
||
сообщение пережило рестарт).
|
||
**НЕ закрыто:** падение самой ВМ — SQS и Redis лежат на одной машине (single point of failure).
|
||
Настоящая отказоустойчивость — после Шага 3 (Redis на отдельном хосте + несколько инстансов).
|
||
|
||
### Дефекты seed, обнаруженные при включении Redis (исправлены, коммит `c0aa618`)
|
||
1. **Демо-очереди не персистились** — после рестарта у демо-тенанта не было очередей.
|
||
Фикс: `persistence.SaveQueue` + `SaveMessages` в `app/cmd/seed.go`.
|
||
2. **Дубли тенантов** — каждый старт создавал нового демо-тенанта (новые креды). При
|
||
`Restart=always` это утечка. Фикс: идемпотентность в `seedDemoData` (проверка по имени
|
||
через `store.List()` → «сид пропущен»).
|
||
|
||
### Для прода
|
||
`SHARED_SQS_SEED_DEMO=false` (демо-данные не нужны), тенанты/очереди создаются через API
|
||
(они персистятся штатно).
|
||
|
||
## 9. Прод-хардненинг (2026-10-10, выполнено)
|
||
|
||
- `SHARED_SQS_SEED_DEMO=false` — демо-данные отключены (существующий тенант подхватывается из Redis).
|
||
- **admin-token сменён** на случайный 64-hex (хранится в `/etc/shared-sqs.env`, 600). Прежний
|
||
`dev-token-123` был слабым, а сервис теперь публичный. Прочитать: `sudo sed -n '1p' /etc/shared-sqs.env`.
|
||
- **logrotate** `/etc/logrotate.d/shared-sqs`: daily, rotate 7, compress, delaycompress,
|
||
copytruncate, `su naeel naeel` (copytruncate — процесс держит файл открытым).
|
||
- Billing (PostgreSQL) и JWT-валидация — **не настроены** (сервис работает без них).
|