8.2 KiB
Публичная точка 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 (эталон)
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. Критичные условия (иначе не работает)
Host $http_host— SigV4 подписывает заголовокHostцеликом (с портом).$hostпорт отбрасывает →SignatureDoesNotMatch. Сервис берёт хост из запроса:app/auth/auth_middleware.go:315-317.- DNS:
sqs.sinefo.ru A 5.172.178.213; делегированиеsinefo.ru→ns3/ns4.ngcloud.ru. Сертификат выдаётся только когда домен резолвится (HTTP-01 через главный nginx, порт 80). - Порт 8443 на 213 занят DNAT-ом транзита (
→ 95.179.252.111:443) — не использовать. - Проксирование тел —
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. Управление
# запуск 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-overrideSHARED_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-server7.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)
- Демо-очереди не персистились — после рестарта у демо-тенанта не было очередей.
Фикс:
persistence.SaveQueue+SaveMessagesвapp/cmd/seed.go. - Дубли тенантов — каждый старт создавал нового демо-тенанта (новые креды). При
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-валидация — не настроены (сервис работает без них).