Переезд: перечень интеграций, привязанных к IP 46.173.16.127 — что ломается молча #3059

Open
opened 2026-08-23 16:49:00 +00:00 by lekss361 · 10 comments
Owner

Эпик: #2989, раннбук окна: #3057.

Перечня не существовало — это первый. Собран разведкой по четырём направлениям с перекрёстной проверкой 2026-08-23. Ниже только то, что проверено замером; предположения помечены отдельно.

Главный принцип отбора: отделить привязку к IP от привязки к DNS-имени. Второе переезд не ломает — достаточно не трогать A-запись. Это типовая ошибка таких перечней, и она в исходных находках была.


🔴 БЛОКЕР: Telegram недостижим с нового хоста

Замер с Poincare (188.246.224.93), четыре дата-центра Telegram:

IP TCP :443 HTTPS
149.154.166.110который отдаёт DNS нет 000 (таймаут)
149.154.167.220 OPEN 302 за 0.11 с
149.154.175.50 нет 000
91.108.56.130 нет 000

С Beget тот же запрос — 302 за 0.34 с. То есть с Selectel отвечает один DC из четырёх, и именно тот, который резолвер не выдаёт. Это не CA, не DNS и не наш файрвол — это фильтрация/маршрутизация подсетей Telegram на стороне провайдера.

Как проявится: tradein-tgbot работает на long-polling, резолвит 149.154.166.110, виснет на таймауте и умирает молча — без исключения, без алерта. Вместе с ним отваливаются алерты бэкапов (ops/lib-backup.sh) и uptime-нотификации (ops/uptime-healthcheck.sh), то есть ломается сам канал, которым мы узнали бы о поломке.

Решить до окна. Варианты: оставить бота на Beget; пустить трафик Telegram через прокси-пул; запрос в поддержку Selectel. Пиннинг рабочего DC — не решение, адреса меняются.


🔴 Провайдер прокси с привязкой по IP

mobileproxy.space — в кабинете привязан egress-IP 46.173.16.127. Причина привязки структурная: camoufox/Playwright не умеет authenticated SOCKS5, поэтому авторизация только по IP. После переезда браузерный скрапинг Авито встанет.

Проявление коварное: по записи волта срабатывание whitelist выглядит не как 407, а как молчаливый разрыв соединения после TCP SYN — в коде это ConnectError/таймаут, неотличимо от «площадка забанила».

Отдельно и срочно: подписки просрочены. ASocks мобильный и mobileproxy — оплата до 2026-08-02, автопродление выключено. Сегодня 23.08. Если в окне часть узлов не ответит, это спишут на переезд, а причина другая.


🟠 Ломается от смены хоста, не от IP

После смены DEPLOY_HOST каталог /opt/gendesign на Beget больше никогда не обновится. Все три workflow делают git reset --hard origin/main именно на DEPLOY_HOST. А на Beget из этого каталога по абсолютным путям исполняются ops/backup.sh, ops/backup-forgejo.sh, ops/check-backup-staleness.sh, ops/docker-prune.sh — все в crontab.

Crontab: 10 задач, не 7 (сегодня добавлены бэкап Forgejo и три сторожа устаревания). После переезда половина сломается на Beget: строки с docker exec tradein-postgres, docker exec tradein-backend и дампом кластера gendesign — этих контейнеров там уже не будет. Скопировать crontab целиком тоже нельзя: сторожа и бэкап Forgejo должны остаться на Beget.

Caddyfile приедет на Selectel целиком — со всеми восемью site-блоками, включая obsidian.gendsgn.ru, errors.gendsgn.ru, git.gendsgn.ru, которые остаются на Beget. Caddy на новом хосте начнёт выпускать для них сертификаты по HTTP-01, а DNS указывает на Beget — ACME будет падать, с риском упереться в rate limit Let's Encrypt.

FDW tradein → gendesign привязан к сетевому алиасу: srvoptions = {host=gendesign-postgres, dbname=gendesign, connect_timeout=3, fetch_size=10000, use_remote_estimate=true}. Работает, только пока оба кластера в одной docker-сети — см. третью мину из #3057 про внешнюю сеть gendesign_shared.

fail2ban и ufw на Beget активны. После переезда 188.246.224.93 станет для него незнакомым источником, постоянно стучащим в 443 (envelope'ы Sentry, SSH-деплои, LiveSync). Любой jail по логам может забанить собственный новый прод.


🟡 Второй периметр: зоопарк с 94.228.121.73

DNS этих доменов живёт не у Beget, а у Timewebns1/ns2.timeweb.ru. Правки идут в другой панели, это отдельный доступ и отдельный человек.

Сертификаты выпускает certbot, а не Caddy, HTTP-01, обновление раз в 60 дней, ошибки уходят в почту root'а, которую никто не читает. Если A-запись переехала, а webroot на новом хосте отличается — первые два месяца всё работает, потом сайты разом отдают истёкший сертификат.

Внешние пуши по адресу старого хоста: Macro CRM бьёт вебхуком в /ai/api/127.0.0.1:8765, а GPU-бокс LMMACHINE шлёт win_status.json через scp в /var/www/ai-analytics/crm/. Дашборд поллит файл каждые 5 секунд и при офлайне «данные молча устаревают». PRINZIP-AI в периметр переезда не входит — значит эти пути надо либо сохранить, либо осознанно оборвать.


Проверено и НЕ ломается — снято с учёта

  • GLITCHTIP_DSN и Obsidian LiveSync привязаны к DNS-имени, а не к IP. В Caddyfile нет ни одного remote_ip-матчера и ни одного trusted_proxies. A-записи остаются на Beget — связь не рвётся. Оба фигурировали в исходных находках как «ломается молча» — неверно.
  • CouchDB не уйдёт в Admin-Party. Пароль задан как ${COUCHDB_PASSWORD:?...} — синтаксис :? роняет compose с ошибкой, а не подставляет пустое значение.
  • Прокси-пул ASocks авторизуется логином-паролем в URL, не по IP клиента. Площадки видят exit-IP прокси — для них переезд нейтрален. (Оговорка про mobileproxy выше — там иначе.)
  • Российский корневой УЦ отсутствует в trust store — но на обоих хостах одинаково: curl https://nspd.gov.ru/ даёт 000 и с Beget, и с Poincare, а с -k200. Это не регресс переезда, а существующее свойство. В исходных находках подано как «новый класс тихой поломки» — неверно.
  • Т-Банк: исходящие не работают ни с одного хоста (TLS alert, unknown CA), и платёжный контур в прод-окружении выключен — PAYMENTS_ENABLED и TBANK_* в env отсутствуют.

🟢 Что переезд, наоборот, чинит

На текущем IP два активных hard-ban'а:

  • НСПД отдаёт 403 с телом Client IP: 46.173.16.127 / Rule: 57615a88d1ec0120b56fdce6. Последний успешный дамп 2026-07-27, 25 ошибочных за 7 дней (#2956).
  • ДОМ.РФ — ServicePipe WAF банит с 2026-05-24, job_settings.scrape_kn enabled=false (#2443).

Свежий IP с высокой вероятностью снимает оба. Но не включать сбор сразу: у НСПД нет брейкера — issue фиксирует прогон, сделавший ещё 9 запросов после первого 403. Сначала одна ручная проба, потом circuit-breaker, потом включение.

Отдельный риск того же рода: geocode_deals_nominatim льёт 5000 адресов в сутки с одного адреса (194 события «429» за неделю). Новый IP сгорит за недели, если ехать как есть.


Почта

Ящики заведены в панели Beget, MX всех четырёх доменов → mx1/mx2.beget.com. Переезд VPS почту не трогает, но закрытие аккаунта Beget убьёт и её, и DNS-зону.

Исходящий SMTP с Poincare: smtp.beget.com:465 OPEN, :25 OPEN, :587 BLOCKED. Дефолтные конфиги Django/GlitchTip с EMAIL_USE_TLS на 587 не заведутся — нужен implicit SSL на 465.

DMARC есть только у meraocenka.ru. У gendsgn.ru, merahome.ru, meraotsenka.ru его нет — отчётов о проблемах доставки после смены IP не будет.


Приёмка

  • Решён вопрос с Telegram — бот и алерты работают после переезда
  • mobileproxy.space: egress-IP в кабинете обновлён на новый
  • Подписки прокси продлены либо признаны ненужными
  • Crontab разведён: что остаётся на Beget, что уезжает
  • Решено, чем обновлять /opt/gendesign на Beget после смены DEPLOY_HOST
  • Caddyfile разведён по хостам — на Selectel не должно быть блоков остающихся доменов
  • fail2ban/ufw на Beget знают новый адрес
  • Зоопарк: доступ к панели Timeweb, план по certbot, судьба внешних пушей
  • После переезда: проба НСПД и ДОМ.РФ с брейкером, пересмотр лимита Nominatim

Refs #3057, #3027, #3031, #2956, #2443

Эпик: #2989, раннбук окна: #3057. Перечня не существовало — это первый. Собран разведкой по четырём направлениям с перекрёстной проверкой 2026-08-23. Ниже только то, что **проверено замером**; предположения помечены отдельно. Главный принцип отбора: отделить привязку к **IP** от привязки к **DNS-имени**. Второе переезд не ломает — достаточно не трогать A-запись. Это типовая ошибка таких перечней, и она в исходных находках была. --- ## 🔴 БЛОКЕР: Telegram недостижим с нового хоста Замер с Poincare (188.246.224.93), четыре дата-центра Telegram: | IP | TCP :443 | HTTPS | |---|---|---| | `149.154.166.110` ← **который отдаёт DNS** | нет | `000` (таймаут) | | `149.154.167.220` | OPEN | **`302` за 0.11 с** | | `149.154.175.50` | нет | `000` | | `91.108.56.130` | нет | `000` | С Beget тот же запрос — **`302` за 0.34 с**. То есть с Selectel отвечает **один DC из четырёх**, и именно тот, который резолвер не выдаёт. Это не CA, не DNS и не наш файрвол — это фильтрация/маршрутизация подсетей Telegram на стороне провайдера. **Как проявится:** `tradein-tgbot` работает на long-polling, резолвит `149.154.166.110`, виснет на таймауте и умирает **молча** — без исключения, без алерта. Вместе с ним отваливаются алерты бэкапов (`ops/lib-backup.sh`) и uptime-нотификации (`ops/uptime-healthcheck.sh`), то есть ломается сам канал, которым мы узнали бы о поломке. **Решить до окна.** Варианты: оставить бота на Beget; пустить трафик Telegram через прокси-пул; запрос в поддержку Selectel. Пиннинг рабочего DC — не решение, адреса меняются. --- ## 🔴 Провайдер прокси с привязкой по IP **`mobileproxy.space`** — в кабинете привязан egress-IP `46.173.16.127`. Причина привязки структурная: camoufox/Playwright не умеет authenticated SOCKS5, поэтому авторизация только по IP. После переезда браузерный скрапинг Авито встанет. Проявление коварное: по записи волта срабатывание whitelist выглядит не как `407`, а как **молчаливый разрыв соединения после TCP SYN** — в коде это `ConnectError`/таймаут, неотличимо от «площадка забанила». **Отдельно и срочно:** подписки просрочены. ASocks мобильный и mobileproxy — оплата до **2026-08-02**, автопродление **выключено**. Сегодня 23.08. Если в окне часть узлов не ответит, это спишут на переезд, а причина другая. --- ## 🟠 Ломается от смены хоста, не от IP **После смены `DEPLOY_HOST` каталог `/opt/gendesign` на Beget больше никогда не обновится.** Все три workflow делают `git reset --hard origin/main` именно на `DEPLOY_HOST`. А на Beget из этого каталога по абсолютным путям исполняются `ops/backup.sh`, `ops/backup-forgejo.sh`, `ops/check-backup-staleness.sh`, `ops/docker-prune.sh` — все в crontab. **Crontab: 10 задач, не 7** (сегодня добавлены бэкап Forgejo и три сторожа устаревания). После переезда половина сломается на Beget: строки с `docker exec tradein-postgres`, `docker exec tradein-backend` и дампом кластера `gendesign` — этих контейнеров там уже не будет. Скопировать crontab целиком тоже нельзя: сторожа и бэкап Forgejo должны остаться на Beget. **`Caddyfile` приедет на Selectel целиком** — со всеми восемью site-блоками, включая `obsidian.gendsgn.ru`, `errors.gendsgn.ru`, `git.gendsgn.ru`, которые **остаются на Beget**. Caddy на новом хосте начнёт выпускать для них сертификаты по HTTP-01, а DNS указывает на Beget — ACME будет падать, с риском упереться в rate limit Let's Encrypt. **FDW `tradein → gendesign`** привязан к сетевому алиасу: `srvoptions = {host=gendesign-postgres, dbname=gendesign, connect_timeout=3, fetch_size=10000, use_remote_estimate=true}`. Работает, только пока оба кластера в одной docker-сети — см. третью мину из #3057 про внешнюю сеть `gendesign_shared`. **fail2ban и ufw на Beget активны.** После переезда `188.246.224.93` станет для него незнакомым источником, постоянно стучащим в 443 (envelope'ы Sentry, SSH-деплои, LiveSync). Любой jail по логам может забанить собственный новый прод. --- ## 🟡 Второй периметр: зоопарк с 94.228.121.73 **DNS этих доменов живёт не у Beget, а у Timeweb** — `ns1/ns2.timeweb.ru`. Правки идут в **другой панели**, это отдельный доступ и отдельный человек. **Сертификаты выпускает certbot, а не Caddy**, HTTP-01, обновление раз в 60 дней, ошибки уходят в почту root'а, которую никто не читает. Если A-запись переехала, а webroot на новом хосте отличается — первые два месяца всё работает, потом сайты разом отдают истёкший сертификат. **Внешние пуши по адресу старого хоста:** Macro CRM бьёт вебхуком в `/ai/api/` → `127.0.0.1:8765`, а GPU-бокс LMMACHINE шлёт `win_status.json` через scp в `/var/www/ai-analytics/crm/`. Дашборд поллит файл каждые 5 секунд и при офлайне «данные молча устаревают». PRINZIP-AI в периметр переезда не входит — значит эти пути надо либо сохранить, либо осознанно оборвать. --- ## ✅ Проверено и НЕ ломается — снято с учёта - **`GLITCHTIP_DSN`** и **Obsidian LiveSync** привязаны к **DNS-имени**, а не к IP. В `Caddyfile` нет ни одного `remote_ip`-матчера и ни одного `trusted_proxies`. A-записи остаются на Beget — связь не рвётся. Оба фигурировали в исходных находках как «ломается молча» — неверно. - **CouchDB не уйдёт в Admin-Party.** Пароль задан как `${COUCHDB_PASSWORD:?...}` — синтаксис `:?` роняет compose с ошибкой, а не подставляет пустое значение. - **Прокси-пул ASocks** авторизуется логином-паролем в URL, не по IP клиента. Площадки видят exit-IP прокси — для них переезд нейтрален. (Оговорка про mobileproxy выше — там иначе.) - **Российский корневой УЦ отсутствует в trust store** — но **на обоих хостах одинаково**: `curl https://nspd.gov.ru/` даёт `000` и с Beget, и с Poincare, а с `-k` — `200`. Это не регресс переезда, а существующее свойство. В исходных находках подано как «новый класс тихой поломки» — неверно. - **Т-Банк**: исходящие не работают **ни с одного** хоста (`TLS alert, unknown CA`), и платёжный контур в прод-окружении выключен — `PAYMENTS_ENABLED` и `TBANK_*` в env отсутствуют. --- ## 🟢 Что переезд, наоборот, чинит На текущем IP **два активных hard-ban'а**: - **НСПД** отдаёт 403 с телом `Client IP: 46.173.16.127 / Rule: 57615a88d1ec0120b56fdce6`. Последний успешный дамп **2026-07-27**, 25 ошибочных за 7 дней (#2956). - **ДОМ.РФ** — ServicePipe WAF банит с 2026-05-24, `job_settings.scrape_kn enabled=false` (#2443). Свежий IP с высокой вероятностью снимает оба. **Но не включать сбор сразу**: у НСПД нет брейкера — issue фиксирует прогон, сделавший ещё 9 запросов после первого 403. Сначала одна ручная проба, потом circuit-breaker, потом включение. Отдельный риск того же рода: `geocode_deals_nominatim` льёт **5000 адресов в сутки** с одного адреса (194 события «429» за неделю). Новый IP сгорит за недели, если ехать как есть. --- ## Почта Ящики заведены в панели Beget, MX всех четырёх доменов → `mx1/mx2.beget.com`. Переезд VPS почту **не трогает**, но закрытие аккаунта Beget убьёт и её, и DNS-зону. Исходящий SMTP с Poincare: `smtp.beget.com:465` **OPEN**, `:25` **OPEN**, `:587` **BLOCKED**. Дефолтные конфиги Django/GlitchTip с `EMAIL_USE_TLS` на 587 не заведутся — нужен implicit SSL на 465. DMARC есть только у `meraocenka.ru`. У `gendsgn.ru`, `merahome.ru`, `meraotsenka.ru` его нет — отчётов о проблемах доставки после смены IP не будет. --- ## Приёмка - [ ] Решён вопрос с Telegram — бот и алерты работают после переезда - [ ] `mobileproxy.space`: egress-IP в кабинете обновлён на новый - [ ] Подписки прокси продлены либо признаны ненужными - [ ] Crontab разведён: что остаётся на Beget, что уезжает - [ ] Решено, чем обновлять `/opt/gendesign` на Beget после смены `DEPLOY_HOST` - [ ] `Caddyfile` разведён по хостам — на Selectel не должно быть блоков остающихся доменов - [ ] fail2ban/ufw на Beget знают новый адрес - [ ] Зоопарк: доступ к панели Timeweb, план по certbot, судьба внешних пушей - [ ] После переезда: проба НСПД и ДОМ.РФ с брейкером, пересмотр лимита Nominatim Refs #3057, #3027, #3031, #2956, #2443
Author
Owner

Проверка замером 2026-08-23: прокси в порядке, Telegram решается закреплением адреса

Прокси: IP-привязки нет, переезд их не трогает

Прогнал все четыре узла scrape_proxies с обоих хостов — URL нигде не печатался.

Узел С Beget С Poincare
asocks-residential-1 200, exit 212.8.249.134, 0.82 с 200, тот же exit, 0.52 с
asocks-mobile-1 200, exit 190.2.145.131, 3.28 с 200, тот же exit, 0.81 с
asocks-mobile-2 200, exit 175.110.115.153, 1.76 с 200, тот же exit, 1.71 с
asocks-mobile-3 200, exit 109.236.82.42, 1.12 с 200, тот же exit, 0.69 с

Exit-IP совпадают, задержки с нового хоста даже ниже. IP-привязки в кабинете ASocks нет — опасение из перечня снято замером, а не рассуждением.

Заявление про просроченные подписки не подтвердилось. last_ok_at у всех четырёх — сегодняшние 17:08–17:20, consecutive_fails=0, disabled_reason пуст. Запись в волте про оплату «до 2026-08-02 с выключенным автопродлением» устарела.

Остаётся непроверенным только mobileproxy.space — он не в scrape_proxies, а в отдельной переменной, и именно у него по волту привязка по egress-IP. Его надо проверить отдельно.

🔴🟢 Telegram: не блокировка Selectel, а частичная фильтрация у обоих провайдеров

Исходный диагноз «Telegram недостижим с нового хоста» оказался неточным. Замер по семи адресам:

IP с Beget с Poincare
149.154.167.220 302 (0.17 с) 302 (0.11 с)
149.154.166.110 ← отдаёт DNS 302 (0.22 с) 000
149.154.167.99 302 (0.86 с) 000
149.154.175.100 000 000
149.154.171.5 000 000
91.108.4.5 000 000
91.108.56.130 000 000

Telegram частично фильтруется у обоих провайдеров — с Beget доступны 3 адреса из 7, с Poincare 1 из 7. Разница только в том, что Beget случайно попадает в тот адрес, который отдаёт резолвер, а Selectel — нет. Это не «Selectel блокирует», и не CA, и не наш файрвол.

Через прокси Telegram не проходит ни с одного узла (все четыре — 000): они российские, а Telegram в РФ блокируется. Этот путь закрыт.

Решение: закрепить 149.154.167.220

Проверено полностью, включая настоящий эндпоинт Bot API:

на хосте:        curl https://api.telegram.org/  → 302, ip=149.154.167.220, 0.11 с
Bot API:         /bot<fake>/getMe → {"ok":false,"error_code":401} за 0.11 с
                 (с Beget тот же ответ за 0.25 с — идентично)
в контейнере:    docker run --add-host api.telegram.org:149.154.167.220 → 302 за 0.125 с
стабильность:    5 запросов подряд → 302 302 302 302 302

Закрепление работает и на уровне хоста, и внутри docker — а бот живёт в контейнере, так что это важно.

Что сделать:

  • extra_hosts: ["api.telegram.org:149.154.167.220"] для tradein-tgbot в compose — декларативно, в git, проходит ревью
  • запись в /etc/hosts нового хоста — для скриптов, которые уведомляют не из контейнера (ops/lib-backup.sh, ops/uptime-healthcheck.sh); на Poincare уже добавлена, бэкап оригинала в /etc/hosts.bak-tgtest

⚠️ Признаю точку отказа

Скан всего 149.154.167.0/24 с Poincare дал ровно один живой адрес. Запасного нет. Если 149.154.167.220 перестанет отвечать — бот умрёт так же молча, как умер бы без закрепления.

Хуже того, канал оповещения об этом сам идёт через Telegram: алерты бэкапов (ops/lib-backup.sh) и uptime-нотификации ходят туда же. Поломка скрывает сама себя.

Поэтому закрепление адреса — необходимое, но не достаточное. Нужен независимый канал оповещения. Кандидат проверен: smtp.beget.com:465 с Poincare OPEN (587 закрыт, 25 открыт). Либо событие в GlitchTip, который остаётся на Beget и доступен по имени.

Обновление приёмки

  • Прокси проверены с нового хоста — IP-привязки нет, переезд их не ломает
  • Подписки прокси: заявление о просрочке опровергнуто, все узлы живые
  • Telegram: причина установлена, решение проверено до эндпоинта Bot API
  • extra_hosts для tradein-tgbot внесён в compose
  • Независимый от Telegram канал алертов (почта через :465 либо GlitchTip)
  • mobileproxy.space проверен отдельно — у него привязка по egress-IP

Refs #3057, #2989

## Проверка замером 2026-08-23: прокси в порядке, Telegram решается закреплением адреса ### ✅ Прокси: IP-привязки нет, переезд их не трогает Прогнал все четыре узла `scrape_proxies` **с обоих хостов** — URL нигде не печатался. | Узел | С Beget | С Poincare | |---|---|---| | `asocks-residential-1` | 200, exit `212.8.249.134`, 0.82 с | 200, тот же exit, **0.52 с** | | `asocks-mobile-1` | 200, exit `190.2.145.131`, 3.28 с | 200, тот же exit, **0.81 с** | | `asocks-mobile-2` | 200, exit `175.110.115.153`, 1.76 с | 200, тот же exit, **1.71 с** | | `asocks-mobile-3` | 200, exit `109.236.82.42`, 1.12 с | 200, тот же exit, **0.69 с** | Exit-IP совпадают, задержки с нового хоста даже ниже. **IP-привязки в кабинете ASocks нет** — опасение из перечня снято замером, а не рассуждением. **Заявление про просроченные подписки не подтвердилось.** `last_ok_at` у всех четырёх — сегодняшние 17:08–17:20, `consecutive_fails=0`, `disabled_reason` пуст. Запись в волте про оплату «до 2026-08-02 с выключенным автопродлением» устарела. Остаётся непроверенным только **`mobileproxy.space`** — он не в `scrape_proxies`, а в отдельной переменной, и именно у него по волту привязка по egress-IP. Его надо проверить отдельно. ### 🔴→🟢 Telegram: не блокировка Selectel, а частичная фильтрация у обоих провайдеров Исходный диагноз «Telegram недостижим с нового хоста» оказался неточным. Замер по семи адресам: | IP | с Beget | с Poincare | |---|---|---| | `149.154.167.220` | 302 (0.17 с) | **302 (0.11 с)** | | `149.154.166.110` ← отдаёт DNS | 302 (0.22 с) | **000** | | `149.154.167.99` | 302 (0.86 с) | 000 | | `149.154.175.100` | 000 | 000 | | `149.154.171.5` | 000 | 000 | | `91.108.4.5` | 000 | 000 | | `91.108.56.130` | 000 | 000 | **Telegram частично фильтруется у обоих провайдеров** — с Beget доступны 3 адреса из 7, с Poincare 1 из 7. Разница только в том, что Beget случайно попадает в тот адрес, который отдаёт резолвер, а Selectel — нет. Это не «Selectel блокирует», и не CA, и не наш файрвол. Через прокси Telegram **не проходит ни с одного узла** (все четыре — `000`): они российские, а Telegram в РФ блокируется. Этот путь закрыт. ### Решение: закрепить `149.154.167.220` Проверено полностью, включая настоящий эндпоинт Bot API: ``` на хосте: curl https://api.telegram.org/ → 302, ip=149.154.167.220, 0.11 с Bot API: /bot<fake>/getMe → {"ok":false,"error_code":401} за 0.11 с (с Beget тот же ответ за 0.25 с — идентично) в контейнере: docker run --add-host api.telegram.org:149.154.167.220 → 302 за 0.125 с стабильность: 5 запросов подряд → 302 302 302 302 302 ``` Закрепление работает и на уровне хоста, и внутри docker — а бот живёт в контейнере, так что это важно. **Что сделать:** - `extra_hosts: ["api.telegram.org:149.154.167.220"]` для `tradein-tgbot` в compose — декларативно, в git, проходит ревью - запись в `/etc/hosts` нового хоста — для скриптов, которые уведомляют не из контейнера (`ops/lib-backup.sh`, `ops/uptime-healthcheck.sh`); на Poincare уже добавлена, бэкап оригинала в `/etc/hosts.bak-tgtest` ### ⚠️ Признаю точку отказа Скан всего `149.154.167.0/24` с Poincare дал **ровно один живой адрес**. Запасного нет. Если `149.154.167.220` перестанет отвечать — бот умрёт так же молча, как умер бы без закрепления. Хуже того, канал оповещения об этом **сам идёт через Telegram**: алерты бэкапов (`ops/lib-backup.sh`) и uptime-нотификации ходят туда же. Поломка скрывает сама себя. **Поэтому закрепление адреса — необходимое, но не достаточное.** Нужен независимый канал оповещения. Кандидат проверен: `smtp.beget.com:465` с Poincare **OPEN** (587 закрыт, 25 открыт). Либо событие в GlitchTip, который остаётся на Beget и доступен по имени. ### Обновление приёмки - [x] Прокси проверены с нового хоста — IP-привязки нет, переезд их не ломает - [x] Подписки прокси: заявление о просрочке опровергнуто, все узлы живые - [x] Telegram: причина установлена, решение проверено до эндпоинта Bot API - [ ] `extra_hosts` для `tradein-tgbot` внесён в compose - [ ] Независимый от Telegram канал алертов (почта через :465 либо GlitchTip) - [ ] `mobileproxy.space` проверен отдельно — у него привязка по egress-IP Refs #3057, #2989
Author
Owner

Решение владельца 2026-08-23: mobileproxy.space не используем, остаётся только ASocks

Пункт про привязку egress-IP в кабинете mobileproxy.space снимается — провайдер выводится из употребления. Прокси-риск переезда закрыт полностью.

Что это значит по фактам замера:

  • Все четыре узла ASocks проверены с обоих хостов и работают одинаково, с теми же exit-IP: 212.8.249.134, 190.2.145.131, 175.110.115.153, 109.236.82.42. С Poincare задержки даже ниже.
  • IP-привязки у ASocks нет — авторизация логином-паролем в URL. Площадки видят exit-IP прокси, а не наш сервер, поэтому смена адреса для них нейтральна.
  • Подписки живы: last_ok_at сегодняшние, consecutive_fails=0, disabled_reason пуст.

Единственная остававшаяся привязка по IP из всего перечня — снята решением, а не обходом. Ничего чинить не нужно.

Побочное следствие, которое стоит держать в голове: у camoufox/Playwright структурная причина, по которой раньше выбирали mobileproxy — он не умеет authenticated SOCKS5, поэтому там была авторизация по IP. Отказ от провайдера означает, что браузерный скрапинг должен ходить через HTTP-прокси ASocks (SCRAPER_PROXY_URL), как и остальной сбор. Если где-то в коде остался путь, завязанный на SOCKS5 без авторизации, он станет мёртвым — проверить при первом же прогоне браузерного сбора после переезда.

Обновление приёмки

  • mobileproxy.space: egress-IP в кабинете обновлён на новый — провайдер не используется
  • Подписки прокси проверены — все узлы живые
  • Прокси проверены с нового хоста — привязки нет

Остаётся из этого перечня:

  • extra_hosts для Telegram (в работе)
  • Независимый от Telegram канал алертов
  • Crontab разведён между хостами
  • Чем обновлять /opt/gendesign на Beget после смены DEPLOY_HOST
  • Caddyfile разведён по хостам
  • fail2ban/ufw на Beget знают новый адрес
  • Зоопарк: панель Timeweb, certbot, внешние пуши
  • После переезда: проба НСПД и ДОМ.РФ с брейкером, лимит Nominatim

Refs #3057

## Решение владельца 2026-08-23: `mobileproxy.space` не используем, остаётся только ASocks Пункт про привязку egress-IP в кабинете `mobileproxy.space` **снимается** — провайдер выводится из употребления. Прокси-риск переезда закрыт полностью. Что это значит по фактам замера: - Все четыре узла ASocks проверены **с обоих хостов** и работают одинаково, с теми же exit-IP: `212.8.249.134`, `190.2.145.131`, `175.110.115.153`, `109.236.82.42`. С Poincare задержки даже ниже. - **IP-привязки у ASocks нет** — авторизация логином-паролем в URL. Площадки видят exit-IP прокси, а не наш сервер, поэтому смена адреса для них нейтральна. - Подписки живы: `last_ok_at` сегодняшние, `consecutive_fails=0`, `disabled_reason` пуст. **Единственная остававшаяся привязка по IP из всего перечня — снята решением, а не обходом.** Ничего чинить не нужно. Побочное следствие, которое стоит держать в голове: у `camoufox`/Playwright структурная причина, по которой раньше выбирали mobileproxy — он не умеет authenticated SOCKS5, поэтому там была авторизация по IP. Отказ от провайдера означает, что браузерный скрапинг должен ходить через HTTP-прокси ASocks (`SCRAPER_PROXY_URL`), как и остальной сбор. Если где-то в коде остался путь, завязанный на SOCKS5 без авторизации, он станет мёртвым — проверить при первом же прогоне браузерного сбора после переезда. ### Обновление приёмки - [x] ~~`mobileproxy.space`: egress-IP в кабинете обновлён на новый~~ — провайдер не используется - [x] Подписки прокси проверены — все узлы живые - [x] Прокси проверены с нового хоста — привязки нет Остаётся из этого перечня: - [ ] `extra_hosts` для Telegram (в работе) - [ ] Независимый от Telegram канал алертов - [ ] Crontab разведён между хостами - [ ] Чем обновлять `/opt/gendesign` на Beget после смены `DEPLOY_HOST` - [ ] `Caddyfile` разведён по хостам - [ ] fail2ban/ufw на Beget знают новый адрес - [ ] Зоопарк: панель Timeweb, certbot, внешние пуши - [ ] После переезда: проба НСПД и ДОМ.РФ с брейкером, лимит Nominatim Refs #3057
Author
Owner

Обновление по списку: два пункта закрыты мержем, третий — в PR #3070.

Закрыто

  • extra_hosts для Telegram — PR #3060, смержен. tradein-mvp/docker-compose.selectel.yml закрепляет 149.154.167.220 для tgbot и backendapi.telegram.org ходит не только бот: app/api/v1/glitchtip.py пересылает алерты, app/api/v1/support.py — support-чат; закрепить только боту значило бы починить треть). Хостовую половину закрывает шаг 11 ops/selectel-bootstrap.sh.
  • Caddyfile разведён по хостам — PR #3062, смержен и проверен на проде: caddy пересоздан, caddy/sites/ смонтирован, все 8 доменов отвечают ровно как до правки. CADDY_SITES=apps → 5 доменов, =infra → 3, без переменной → 8.

В работе

  • Независимый от Telegram канал алертовPR #3070.

    Суть: notify() при отказе Telegram ограничивался || log "WARN" — алерт терялся, оставалась строка в логе. Теперь при отказе (и при ненастроенном Telegram) пробуется почта, а если и она не настроена — в лог идёт громкая строка «АЛЕРТ НЕ ДОСТАВЛЕН» вместо тихого WARN.

    Транспорт — curl через smtps://smtp.beget.com:465 (порт проверен OPEN с Poincare). Креды из того же env-файла, что и Telegram; в репозитории их нет. Ничего не настроено → поведение ровно как раньше.

    Честно про проверку: негативные ветки прогнаны все (не настроено / SMTP недоступен / notify без Telegram / пароль не течёт в вывод — 0 вхождений). Успешную доставку не проверял — нужны настоящие креды. Три попытки поднять фейковый SMTP-сервер положительного контроля не дали, и записывать «наверное работает» я не стал: без положительного контроля зелёные негативные тесты доказывают только то, что код правильно падает.

    Чтобы канал заработал — дописать пять переменных в /etc/default/gendesign-backup и один раз проверить доставку. Детали в PR.

Остаётся

  • Crontab разведён между хостами
  • Чем обновлять /opt/gendesign на Beget после смены DEPLOY_HOST
  • fail2ban/ufw на Beget знают новый адрес
  • Зоопарк: панель Timeweb, certbot, внешние пуши — владелец
  • После переезда: проба НСПД и ДОМ.РФ с брейкером, лимит Nominatim

Отдельно к перечню «что ломается молча» стоит добавить находки из инвентаря зоопарка (#3031), которых в исходном списке не было: tailscaled (идентичность узла меняется при переезде — доступ отвалится без ошибки), zabbix-agent (внешний Zabbix продолжит опрашивать мёртвый адрес), xray на порту 8752 (назначение не установлено).

Обновление по списку: два пункта закрыты мержем, третий — в PR #3070. ## Закрыто - [x] **`extra_hosts` для Telegram** — PR #3060, смержен. `tradein-mvp/docker-compose.selectel.yml` закрепляет `149.154.167.220` для `tgbot` **и** `backend` (в `api.telegram.org` ходит не только бот: `app/api/v1/glitchtip.py` пересылает алерты, `app/api/v1/support.py` — support-чат; закрепить только боту значило бы починить треть). Хостовую половину закрывает шаг 11 `ops/selectel-bootstrap.sh`. - [x] **`Caddyfile` разведён по хостам** — PR #3062, смержен **и проверен на проде**: caddy пересоздан, `caddy/sites/` смонтирован, все 8 доменов отвечают ровно как до правки. `CADDY_SITES=apps` → 5 доменов, `=infra` → 3, без переменной → 8. ## В работе - [ ] **Независимый от Telegram канал алертов** → **PR #3070**. Суть: `notify()` при отказе Telegram ограничивался `|| log "WARN"` — алерт терялся, оставалась строка в логе. Теперь при отказе (и при ненастроенном Telegram) пробуется почта, а если и она не настроена — в лог идёт **громкая** строка «АЛЕРТ НЕ ДОСТАВЛЕН» вместо тихого WARN. Транспорт — `curl` через `smtps://smtp.beget.com:465` (порт проверен OPEN с Poincare). Креды из того же env-файла, что и Telegram; в репозитории их нет. Ничего не настроено → поведение ровно как раньше. **Честно про проверку:** негативные ветки прогнаны все (не настроено / SMTP недоступен / notify без Telegram / пароль не течёт в вывод — 0 вхождений). **Успешную доставку не проверял** — нужны настоящие креды. Три попытки поднять фейковый SMTP-сервер положительного контроля не дали, и записывать «наверное работает» я не стал: без положительного контроля зелёные негативные тесты доказывают только то, что код правильно падает. Чтобы канал заработал — дописать пять переменных в `/etc/default/gendesign-backup` и один раз проверить доставку. Детали в PR. ## Остаётся - [ ] Crontab разведён между хостами - [ ] Чем обновлять `/opt/gendesign` на Beget после смены `DEPLOY_HOST` - [ ] fail2ban/ufw на Beget знают новый адрес - [ ] Зоопарк: панель Timeweb, certbot, внешние пуши — **владелец** - [ ] После переезда: проба НСПД и ДОМ.РФ с брейкером, лимит Nominatim Отдельно к перечню «что ломается молча» стоит добавить находки из инвентаря зоопарка (#3031), которых в исходном списке не было: **`tailscaled`** (идентичность узла меняется при переезде — доступ отвалится без ошибки), **`zabbix-agent`** (внешний Zabbix продолжит опрашивать мёртвый адрес), **`xray`** на порту 8752 (назначение не установлено).
Author
Owner

Закрыл разведкой пункт «fail2ban/ufw на Beget знают новый адрес». Оказалось, что смотреть надо в другую сторону, и там нашлось то, что может остановить деплой на сутки.

Проверка Beget — чисто

ignoreip = 127.0.0.1/8 ::1, адресных правил в ufw нет. После переезда Beget становится источником SSH-соединений, а не целью, так что его fail2ban в деплойном пути не участвует. Пункт в исходной формулировке закрывается ничем.

А вот Poincare — реальный риск

Там fail2ban активен, jail sshd, и адреса Beget в whitelist нет:

ignoreip   127.0.0.1/8 ::1
maxretry   10
findtime   3600      (1 час)
bantime    86400     (24 ЧАСА)

Jail не декоративный — он работает прямо сейчас:

Currently banned: 21
Total banned:     47

Почему это опасно именно в окне

После переезда раннер на Beget ходит по SSH на Poincare на каждом деплое, причём несколькими шагами (deploy, deploy-caddy, плюс отдельный проход tradein-пайплайна). При корректном ключе отказов нет — риск не в штатной работе.

Риск в том, что #3029 планирует ровно ту операцию, которая эти отказы порождает: «Новый deploy-ключ выпущен, старый отозван». Любое рассогласование в момент ротации — ключ выпущен, но не разложен; не тот пользователь; не тот порт — даёт серию неудачных аутентификаций. Десять за час, и 46.173.16.127 уезжает в бан на сутки.

Последствие: деплой перестаёт работать целиком, а выглядит это как сетевая проблема, а не как бан. Именно так меня сегодня ночью отрезал сервер Антона — серия коротких переподключений, потом Connection timed out без каких-либо объяснений. На то, чтобы понять причину, ушло время; в окне переезда такого запаса не будет.

Отдельно стоит помнить, что канал оповещения об этом сам может оказаться недоступен (#2203TELEGRAM_* не настроен нигде).

Что сделать — одна строка, но до окна

Внести адрес Beget в whitelist на Poincare до ротации ключа:

# /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 46.173.16.127

затем fail2ban-client reload, проверить fail2ban-client get sshd ignoreip.

Сам не делаю: это правка конфигурации безопасности на хосте, который станет продом, и решение о whitelist — твоё. Готов выполнить по слову.

Побочно замеченное

На Poincare PermitRootLogin yes. Констатирую факт без рекомендации — деплой ходит под отдельным пользователем, так что для переезда это не блокер, но root по SSH открыт в интернет на машине, которая будет держать оба продуктовых кластера и ПДн-базы. Стоит решить осознанно, а не оставить по умолчанию.

Обновление списка

  • fail2ban/ufw на Beget знают новый адресне требуется: Beget становится источником, не целью
  • Новое: whitelist Beget в fail2ban на Poincare — до ротации ключа из #3029
  • PermitRootLogin на Poincare — решить осознанно
Закрыл разведкой пункт «fail2ban/ufw на Beget знают новый адрес». Оказалось, что смотреть надо **в другую сторону**, и там нашлось то, что может остановить деплой на сутки. ## Проверка Beget — чисто `ignoreip = 127.0.0.1/8 ::1`, адресных правил в `ufw` нет. После переезда Beget становится **источником** SSH-соединений, а не целью, так что его fail2ban в деплойном пути не участвует. Пункт в исходной формулировке закрывается ничем. ## А вот Poincare — реальный риск Там fail2ban **активен**, jail `sshd`, и адреса Beget в whitelist нет: ``` ignoreip 127.0.0.1/8 ::1 maxretry 10 findtime 3600 (1 час) bantime 86400 (24 ЧАСА) ``` Jail не декоративный — он **работает прямо сейчас**: ``` Currently banned: 21 Total banned: 47 ``` ## Почему это опасно именно в окне После переезда раннер на Beget ходит по SSH на Poincare **на каждом деплое**, причём несколькими шагами (`deploy`, `deploy-caddy`, плюс отдельный проход tradein-пайплайна). При корректном ключе отказов нет — риск не в штатной работе. Риск в том, что **#3029 планирует ровно ту операцию, которая эти отказы порождает**: «Новый deploy-ключ выпущен, старый отозван». Любое рассогласование в момент ротации — ключ выпущен, но не разложен; не тот пользователь; не тот порт — даёт серию неудачных аутентификаций. Десять за час, и `46.173.16.127` уезжает в бан **на сутки**. Последствие: деплой перестаёт работать целиком, а выглядит это как сетевая проблема, а не как бан. Именно так меня сегодня ночью отрезал сервер Антона — серия коротких переподключений, потом `Connection timed out` без каких-либо объяснений. На то, чтобы понять причину, ушло время; в окне переезда такого запаса не будет. Отдельно стоит помнить, что канал оповещения об этом сам может оказаться недоступен (#2203 — `TELEGRAM_*` не настроен нигде). ## Что сделать — одна строка, но до окна Внести адрес Beget в whitelist на Poincare **до** ротации ключа: ``` # /etc/fail2ban/jail.local [DEFAULT] ignoreip = 127.0.0.1/8 ::1 46.173.16.127 ``` затем `fail2ban-client reload`, проверить `fail2ban-client get sshd ignoreip`. Сам не делаю: это правка конфигурации безопасности на хосте, который станет продом, и решение о whitelist — твоё. Готов выполнить по слову. ## Побочно замеченное На Poincare `PermitRootLogin yes`. Констатирую факт без рекомендации — деплой ходит под отдельным пользователем, так что для переезда это не блокер, но root по SSH открыт в интернет на машине, которая будет держать оба продуктовых кластера и ПДн-базы. Стоит решить осознанно, а не оставить по умолчанию. ## Обновление списка - [x] ~~fail2ban/ufw на Beget знают новый адрес~~ — **не требуется**: Beget становится источником, не целью - [ ] **Новое:** whitelist Beget в fail2ban на Poincare — до ротации ключа из #3029 - [ ] `PermitRootLogin` на Poincare — решить осознанно
Author
Owner

Перепроверка блокера по Telegram уже ПОСЛЕ переезда (2026-08-26 05:55 UTC)

Перечень собирался 23.08, когда продукты ещё стояли на Beget. Продукты переехали 25.08, бот работает на Poincare сутки — есть фактические данные вместо прогноза. Диагноз подтверждается, но проявление оказалось не тем, что ожидалось.

Подтверждено: три дата-центра из четырёх с Poincare недостижимы

IP HTTPS время
149.154.166.110 000 таймаут 8 с
149.154.167.220 302 0.12 с
149.154.175.50 000 таймаут 8 с
91.108.56.130 000 таймаут 8 с

Ровно как в исходном замере. Фильтрация подсетей Telegram у Selectel никуда не делась.

Новое: резолверы расходятся, и это сейчас спасает бота

  • Публичный резолвер (@8.8.8.8) отдаёт 149.154.166.110 — недостижимый.
  • Локальный резолвер хоста отдаёт 149.154.167.220 — рабочий, TTL 0.

Поэтому обращение по имени с Poincare идёт на живой DC: 5 попыток подряд — 302 за 0.11–0.12 с. Бот не умер молча, как предсказывалось: он работает.

Но работает с потерями — 106 таймаутов за сутки

Лог tradein-tgbot за 24 ч: 106 сетевых ошибок getUpdates, из них 97 вылечились первой повторной попыткой, 9 — второй, 9 дошли до ERROR с httpx.ReadTimeout. Конфигурация клиента корректна (long-poll 30 с при HTTP-таймауте 40 с, запас есть) — то есть дело не в ней.

Распределение по часам ровное, без всплесков: 00h—8, 01h—15, 02h—14, 03h—12, 04h—13, 05h—10, 20h—11, 21h—7, 22h—10, 23h—7. Это против гипотезы «DNS иногда отдаёт мёртвый DC» — тогда были бы пачки длиной в TTL. Ровный фон ~4 % отказов при опросе раз в 30 с больше похож на частичную потерю пакетов на пути к Telegram, а не на бинарную блокировку.

Что это меняет для окна 30.08

Блокер не снят, а замаскирован: работоспособность держится на том, что резолвер хоста возвращает единственный доступный DC. Это хрупко — смена резолвера, вывод этого DC из эксплуатации или изменение маршрутизации возвращают исходный сценарий. И канал остаётся тем же, по которому ходят алерты бэкапов (ops/lib-backup.sh) и uptime-нотификации: отказ будет тихим.

Варианты из issue (оставить бота на Beget / пустить трафик Telegram через прокси-пул / запрос в поддержку Selectel) остаются в силе — я лишь снимаю срочность «бот не поднимется вовсе»: он поднялся и сутки работает с ~4 % отказов, которые сами себя чинят ретраями.

Поправка к моему же комментарию в #3057

Там я отнёс эти таймауты к «сетевым обрывам, не дефекту». Формально верно, но связи с этим блокером я тогда не увидел — она есть, и причина именно та, что описана здесь.

Второй пункт перечня — про прокси — проверить пока нечем

mobileproxy.space с привязкой к egress 46.173.16.127: по действующему решению он выведен из использования, работает ASocks, и текстовый скрап живой (109 543 объявления, свежие 04:44 UTC). Но браузерный сбор Авито с переезда ни разу не запускался: avito_full_load_exhaustive идёт раз в неделю по субботам, последний прогон 23.08 (убит деплоем), следующий — 30.08, то есть прямо в окно переезда. До него проверка невозможна, а сам прогон совпадает с окном — стоит либо дёрнуть его вручную заранее, либо не считать его результат показательным.

## Перепроверка блокера по Telegram уже ПОСЛЕ переезда (2026-08-26 05:55 UTC) Перечень собирался 23.08, когда продукты ещё стояли на Beget. Продукты переехали 25.08, бот работает на Poincare сутки — есть фактические данные вместо прогноза. Диагноз подтверждается, но проявление оказалось не тем, что ожидалось. ### Подтверждено: три дата-центра из четырёх с Poincare недостижимы | IP | HTTPS | время | |---|---|---| | 149.154.166.110 | `000` | таймаут 8 с | | **149.154.167.220** | **302** | **0.12 с** | | 149.154.175.50 | `000` | таймаут 8 с | | 91.108.56.130 | `000` | таймаут 8 с | Ровно как в исходном замере. Фильтрация подсетей Telegram у Selectel никуда не делась. ### Новое: резолверы расходятся, и это сейчас спасает бота - Публичный резолвер (`@8.8.8.8`) отдаёт **149.154.166.110** — недостижимый. - **Локальный резолвер хоста отдаёт 149.154.167.220** — рабочий, TTL 0. Поэтому обращение по имени с Poincare идёт на живой DC: 5 попыток подряд — `302` за 0.11–0.12 с. Бот **не умер молча**, как предсказывалось: он работает. ### Но работает с потерями — 106 таймаутов за сутки Лог `tradein-tgbot` за 24 ч: 106 сетевых ошибок `getUpdates`, из них 97 вылечились первой повторной попыткой, 9 — второй, **9 дошли до ERROR** с `httpx.ReadTimeout`. Конфигурация клиента корректна (long-poll 30 с при HTTP-таймауте 40 с, запас есть) — то есть дело не в ней. Распределение по часам ровное, без всплесков: 00h—8, 01h—15, 02h—14, 03h—12, 04h—13, 05h—10, 20h—11, 21h—7, 22h—10, 23h—7. Это **против** гипотезы «DNS иногда отдаёт мёртвый DC» — тогда были бы пачки длиной в TTL. Ровный фон ~4 % отказов при опросе раз в 30 с больше похож на частичную потерю пакетов на пути к Telegram, а не на бинарную блокировку. ### Что это меняет для окна 30.08 Блокер **не снят, а замаскирован**: работоспособность держится на том, что резолвер хоста возвращает единственный доступный DC. Это хрупко — смена резолвера, вывод этого DC из эксплуатации или изменение маршрутизации возвращают исходный сценарий. И канал остаётся тем же, по которому ходят алерты бэкапов (`ops/lib-backup.sh`) и uptime-нотификации: отказ будет тихим. Варианты из issue (оставить бота на Beget / пустить трафик Telegram через прокси-пул / запрос в поддержку Selectel) остаются в силе — я лишь снимаю срочность «бот не поднимется вовсе»: он поднялся и сутки работает с ~4 % отказов, которые сами себя чинят ретраями. ### Поправка к моему же комментарию в #3057 Там я отнёс эти таймауты к «сетевым обрывам, не дефекту». Формально верно, но связи с этим блокером я тогда не увидел — она есть, и причина именно та, что описана здесь. ### Второй пункт перечня — про прокси — проверить пока нечем `mobileproxy.space` с привязкой к egress `46.173.16.127`: по действующему решению он выведен из использования, работает ASocks, и текстовый скрап живой (109 543 объявления, свежие 04:44 UTC). Но **браузерный** сбор Авито с переезда ни разу не запускался: `avito_full_load_exhaustive` идёт раз в неделю по субботам, последний прогон 23.08 (убит деплоем), следующий — **30.08, то есть прямо в окно переезда**. До него проверка невозможна, а сам прогон совпадает с окном — стоит либо дёрнуть его вручную заранее, либо не считать его результат показательным.
Author
Owner

Статус после переезда (26.08, утро) — оставляю открытой, но перечень сильно сузился.

Переезд состоялся 25.08 в 19:36 UTC, окно 7 мин 38 с. Что из этого перечня закрылось фактом:

Telegram — блокер снят, диагноз в задаче был неполным. Первоначальный вывод «отвечает один DC, пиннинг не решение» проверен серией замеров вместо одиночной пробы: 149.154.167.220:443 открыт, ICMP 3/3 (RTT 35 мс), TLS-рукопожатие из контейнера бота 18 из 20 (контроль github 10/10), getMe реальным токеном 4 из 4, бот @MERAsupport_bot отвечает. Ломается не сеть, а конкретно длинный long-poll: getUpdates?timeout=0 — 4 из 5, getUpdates?timeout=30 — 0 из 3. Характерно для DPI. Пин из #3093 выбран верно и делает ровно то, ради чего сделан. Бот функционален, но шумит: обрыв раз в 1-4 минуты, ретрай подхватывает, сообщения не теряются (Telegram копит апдейты по offset).

Остаточная задача по коду, не срочная: poll_timeout_s: int = 30 зашит в сигнатуру app/services/tgbot/bridge.py:702, из конфига не настраивается — вынести в настройку и поставить 10-15 с. Заодно логировать текст ошибки: сейчас в логах tg client: getUpdates — network error с пустым текстом, и это стоило времени на диагностику.

Crontab разведён и проверен ночным прогоном. Beget — 5 строк (бэкапы forgejo и couchdb плюс сторожа), Poincare — 9 строк. Коллизий имён в S3 нет. Обе ночные заливки прошли: S3 upload OK в 00:39 UTC, Выгрузка в S3 ok в 01:31 UTC.

Caddyfile разведён по хостамCADDY_SITES=apps|infra. Пять боевых доменов на Poincare, четыре инфраструктурных (git, errors, obsidian, garmin) на Beget, ACME на чужие домены не выпускается.

FDW жив. srvoptions через сетевой алиас gendesign-postgres, проверено чтением: gendesign_rosreestr_deals 7 571 875, gendesign_cad_buildings 47 111, gendesign_osm_poi_ekb 4847, quarter_price_index 1986. Пятая таблица gendesign_ekb_districts_geom отдаёт permission denied for view — но ровно так же было и на Beget, гранта у tradein_fdw_reader не было никогда, за 72 ч ноль обращений. Не регресс переезда.

Обновление /opt/gendesign на Beget — решено: инфраструктурный деплой ходит по INFRA_DEPLOY_HOST=46.173.16.127.

Остаётся открытым и требует владельца либо доступа, которого у меня нет:

  • mobileproxy.space — egress-IP в кабинете обновить на 188.246.224.93
  • подписки прокси (ASocks мобильный, mobileproxy) — оплата истекла 02.08, автопродление выключено
  • зоопарк 94.228.121.73: доступ к панели Timeweb, план по certbot, судьба вебхука Macro CRM и scp с LMMACHINE
  • fail2ban/ufw на Beget должны знать новый адрес
  • проба НСПД и ДОМ.РФ с нового IP — только после circuit-breaker'а, у НСПД его нет (в #2956 зафиксирован прогон, сделавший ещё 9 запросов после первого 403)
  • пересмотр лимита geocode_deals_nominatim — 5000 адресов в сутки с одного адреса сожгут свежий IP

Сужение периметра доступа вынесено в #3075.

Статус после переезда (26.08, утро) — оставляю открытой, но перечень сильно сузился. Переезд состоялся 25.08 в 19:36 UTC, окно 7 мин 38 с. Что из этого перечня закрылось фактом: **Telegram — блокер снят, диагноз в задаче был неполным.** Первоначальный вывод «отвечает один DC, пиннинг не решение» проверен серией замеров вместо одиночной пробы: `149.154.167.220:443` открыт, ICMP 3/3 (RTT 35 мс), TLS-рукопожатие из контейнера бота **18 из 20** (контроль github 10/10), `getMe` реальным токеном **4 из 4**, бот `@MERAsupport_bot` отвечает. Ломается не сеть, а конкретно длинный long-poll: `getUpdates?timeout=0` — 4 из 5, `getUpdates?timeout=30` — 0 из 3. Характерно для DPI. Пин из #3093 выбран верно и делает ровно то, ради чего сделан. Бот функционален, но шумит: обрыв раз в 1-4 минуты, ретрай подхватывает, сообщения не теряются (Telegram копит апдейты по offset). Остаточная задача по коду, не срочная: `poll_timeout_s: int = 30` зашит в сигнатуру `app/services/tgbot/bridge.py:702`, из конфига не настраивается — вынести в настройку и поставить 10-15 с. Заодно логировать текст ошибки: сейчас в логах `tg client: getUpdates — network error` с пустым текстом, и это стоило времени на диагностику. **Crontab разведён и проверен ночным прогоном.** Beget — 5 строк (бэкапы forgejo и couchdb плюс сторожа), Poincare — 9 строк. Коллизий имён в S3 нет. Обе ночные заливки прошли: `S3 upload OK` в 00:39 UTC, `Выгрузка в S3 ok` в 01:31 UTC. **Caddyfile разведён по хостам** — `CADDY_SITES=apps|infra`. Пять боевых доменов на Poincare, четыре инфраструктурных (`git`, `errors`, `obsidian`, `garmin`) на Beget, ACME на чужие домены не выпускается. **FDW жив.** `srvoptions` через сетевой алиас `gendesign-postgres`, проверено чтением: `gendesign_rosreestr_deals` 7 571 875, `gendesign_cad_buildings` 47 111, `gendesign_osm_poi_ekb` 4847, `quarter_price_index` 1986. Пятая таблица `gendesign_ekb_districts_geom` отдаёт `permission denied for view` — но ровно так же было и на Beget, гранта у `tradein_fdw_reader` не было никогда, за 72 ч ноль обращений. Не регресс переезда. **Обновление `/opt/gendesign` на Beget** — решено: инфраструктурный деплой ходит по `INFRA_DEPLOY_HOST=46.173.16.127`. Остаётся открытым и требует владельца либо доступа, которого у меня нет: - [ ] `mobileproxy.space` — egress-IP в кабинете обновить на `188.246.224.93` - [ ] подписки прокси (ASocks мобильный, mobileproxy) — оплата истекла 02.08, автопродление выключено - [ ] зоопарк `94.228.121.73`: доступ к панели Timeweb, план по certbot, судьба вебхука Macro CRM и scp с LMMACHINE - [ ] fail2ban/ufw на Beget должны знать новый адрес - [ ] проба НСПД и ДОМ.РФ с нового IP — **только после circuit-breaker'а**, у НСПД его нет (в #2956 зафиксирован прогон, сделавший ещё 9 запросов после первого 403) - [ ] пересмотр лимита `geocode_deals_nominatim` — 5000 адресов в сутки с одного адреса сожгут свежий IP Сужение периметра доступа вынесено в #3075.
Author
Owner

Перепроверка трёх пунктов приёмки на живых хостах, 26.08

Продукты уже стоят на Poincare, поэтому часть перечня можно не предсказывать, а замерить. Ниже — что изменилось против разведки 23.08.


🔴🟡 Telegram: блокер в исходной формулировке не воспроизводится

Замерял с Poincare заново, включая контрольный опыт с Beget.

Что было записано 23.08: резолвер отдаёт 149.154.166.110, этот ДЦ с Selectel не отвечает, бот повиснет и умрёт молча.

Что на самом деле сейчас:

Проверка Результат
Резолв api.telegram.org (12 подряд, хост) 12 из 12 → 149.154.167.220 — тот ДЦ, который отвечает
Резолв из контейнера tradein-tgbot (6 подряд) 6 из 6 → тот же .220
HTTPS-запросы из контейнера бота 10 успешных из 10 (302 за 0.11 с)
Контейнер бота Up, restarts=0

То есть DNS стабильно отдаёт маршрутизируемый ДЦ, и бот работает. Молчаливой смерти, которой опасались, не произошло.

Что осталось верным: из четырёх ДЦ с Poincare отвечает по-прежнему только один (.220; .166.110, .175.50, 91.108.56.130 — таймаут). Запас прочности нулевой: если Telegram сменит запись, канал ляжет.

Остаточный симптом. За 40 минут жизни контейнера — 7 строк getUpdates — network error (попытка 1/3), все восстановились с первого ретрая, ни одного исчерпанного (3/3). Порядка 9 % опросов, потерь сообщений нет.

Контрольный опыт — важен, потому что он снял ложную улику. Простаивающее TLS-соединение к .220 рвётся ровно через 60.1 с, дважды из двух, чистым FIN. Напрашивалось записать это в «Selectel режет длинные соединения». Проверил с Beget теми же двумя пробами — 60.1 с, тоже дважды из двух. Значит это штатный keepalive самого Telegram, к переезду отношения не имеет, и в перечень мин ему не место.

Механизм остаточных ошибок не установлен: воспроизвести long-poll без боевого токена нельзя, а дёргать getUpdates рабочим токеном я не стал — это увело бы апдейты у живого бота.

Предлагаю понизить с блокера до наблюдения. Решение «оставить бота на Beget / пустить через прокси / писать в поддержку» остаётся за владельцем, но выбирать его теперь можно не в режиме аварии.


Crontab разведён — пункт закрыт, проверено на обоих хостах

Beget (gendesign и root — одинаковые):

15 4 * * *  backup-forgejo.sh
45 4 * * *  backup-couchdb.sh
0  * * * *  check-backup-staleness.sh × 2 (forgejo, couchdb)
0  4 * * 0  docker-prune.sh

Poincare:

30 3 * * *  ops/backup.sh                       (gendesign)
30 4 * * *  backup-tradein-db.sh                (tradein)
0  * * * *  check-backup-staleness.sh × 2       (gendesign main, tradein)
15 2 1 * *  restore-drill.sh                    (ежемесячная репетиция)
0/30/45 5 * * *  dadata-backfill / geocode / nominatim
0  4 * * 0  docker-prune.sh

Разведено ровно по смыслу: то, что требует docker exec tradein-*, уехало; сторожа Forgejo и CouchDB остались. Бэкапы идут по факту, а не по расписанию на бумаге: дамп gendesign 26.08 03:39 (1.47 ГБ) и tradein 26.08 04:31 лежат на Poincare.

Отдельно отмечу ложную тревогу, чтобы её не поднимали снова: на Beget сентинелы backups/.last_success (39 ч) и backups/tradein/.last_success (38 ч) выглядят просроченными. Это хвосты, оставшиеся от переноса задач, — соответствующих строк в кроне Beget больше нет, и сторож их уже не проверяет. Удалить их стоит, иначе следующий, кто посмотрит, потратит время так же, как я.


⚠️ Caddy: механизм на месте, но переключён только наполовину — и у этого есть дата

Проверял не конфиг, а что Caddy реально обслуживает (caddy adapt на живых контейнерах).

Хост Обслуживаемые домены
Beget git, errors, obsidian, metrics (+garmin) — только инфраструктура, верно
Poincare gendsgn.ru, www, merahome, meraocenka, meraotsenka + git, errors, obsidian, metrics

Poincare тянет оба файла: CADDY_SITES там не задан, а дефолт в Caddyfile:51*. По задумке так и есть («в окне на Selectel CADDY_SITES=apps»), то есть это не поломка, а невыполненный пока шаг окна.

Сегодня это безвредно: DNS этих трёх доменов смотрит на Beget, трафик до Poincare не доходит. Но сертификаты на Poincare уже лежат — приехали вместе с данными — и у них есть сроки обновления:

Сертификат на Poincare Окно обновления
obsidian.gendsgn.ru 06–08.09.2026
git.gendsgn.ru 12–14.09.2026
metrics.gendsgn.ru 24–26.10.2026

Через одиннадцать дней после окна Poincare начнёт обновлять сертификат домена, который живёт на другой машине: HTTP-01 пойдёт на Beget, проверка не пройдёт, и попытки будут повторяться — ровно тот сценарий с rate limit, о котором issue предупреждает. Само не рассосётся.

Ставить CADDY_SITES=apps прямо сейчас не стал: боевой Caddy, неделя переезда, а выигрыш — устранение риска, который выстрелит не раньше 6 сентября. Это шаг окна, и в раннбуке ему место с явной датой-дедлайном, а не в списке «когда-нибудь».


Обновление приёмки

  • Решён вопрос с Telegramпонижено до наблюдения, бот работает, решение за владельцем без спешки
  • Crontab разведён — проверено на обоих хостах, бэкапы идут
  • Caddyfile разведён по хостам — на Beget сделано, на Poincare нет; CADDY_SITES=apps в шаг окна, дедлайн 06.09
  • Остальные пункты — без изменений, требуют владельца

Мелочью: убрать на Beget осиротевшие сентинелы backups/.last_success и backups/tradein/.last_success.

## Перепроверка трёх пунктов приёмки на живых хостах, 26.08 Продукты уже стоят на Poincare, поэтому часть перечня можно не предсказывать, а замерить. Ниже — что изменилось против разведки 23.08. --- ## 🔴 → 🟡 Telegram: блокер в исходной формулировке не воспроизводится Замерял с Poincare заново, включая контрольный опыт с Beget. **Что было записано 23.08:** резолвер отдаёт `149.154.166.110`, этот ДЦ с Selectel не отвечает, бот повиснет и умрёт молча. **Что на самом деле сейчас:** | Проверка | Результат | |---|---| | Резолв `api.telegram.org` (12 подряд, хост) | **12 из 12 → `149.154.167.220`** — тот ДЦ, который отвечает | | Резолв из контейнера `tradein-tgbot` (6 подряд) | 6 из 6 → тот же `.220` | | HTTPS-запросы из контейнера бота | **10 успешных из 10** (302 за 0.11 с) | | Контейнер бота | `Up`, **restarts=0** | То есть DNS стабильно отдаёт маршрутизируемый ДЦ, и бот работает. Молчаливой смерти, которой опасались, не произошло. **Что осталось верным:** из четырёх ДЦ с Poincare отвечает по-прежнему **только один** (`.220`; `.166.110`, `.175.50`, `91.108.56.130` — таймаут). Запас прочности нулевой: если Telegram сменит запись, канал ляжет. **Остаточный симптом.** За 40 минут жизни контейнера — 7 строк `getUpdates — network error (попытка 1/3)`, **все восстановились с первого ретрая**, ни одного исчерпанного (`3/3`). Порядка 9 % опросов, потерь сообщений нет. **Контрольный опыт — важен, потому что он снял ложную улику.** Простаивающее TLS-соединение к `.220` рвётся ровно через **60.1 с**, дважды из двух, чистым FIN. Напрашивалось записать это в «Selectel режет длинные соединения». Проверил с Beget теми же двумя пробами — **60.1 с, тоже дважды из двух**. Значит это штатный keepalive самого Telegram, к переезду отношения не имеет, и в перечень мин ему не место. Механизм остаточных ошибок не установлен: воспроизвести long-poll без боевого токена нельзя, а дёргать `getUpdates` рабочим токеном я не стал — это увело бы апдейты у живого бота. **Предлагаю понизить с блокера до наблюдения.** Решение «оставить бота на Beget / пустить через прокси / писать в поддержку» остаётся за владельцем, но выбирать его теперь можно не в режиме аварии. --- ## ✅ Crontab разведён — пункт закрыт, проверено на обоих хостах **Beget** (`gendesign` и `root` — одинаковые): ``` 15 4 * * * backup-forgejo.sh 45 4 * * * backup-couchdb.sh 0 * * * * check-backup-staleness.sh × 2 (forgejo, couchdb) 0 4 * * 0 docker-prune.sh ``` **Poincare:** ``` 30 3 * * * ops/backup.sh (gendesign) 30 4 * * * backup-tradein-db.sh (tradein) 0 * * * * check-backup-staleness.sh × 2 (gendesign main, tradein) 15 2 1 * * restore-drill.sh (ежемесячная репетиция) 0/30/45 5 * * * dadata-backfill / geocode / nominatim 0 4 * * 0 docker-prune.sh ``` Разведено ровно по смыслу: то, что требует `docker exec tradein-*`, уехало; сторожа Forgejo и CouchDB остались. **Бэкапы идут по факту, а не по расписанию на бумаге:** дамп gendesign 26.08 03:39 (1.47 ГБ) и tradein 26.08 04:31 лежат на Poincare. Отдельно отмечу ложную тревогу, чтобы её не поднимали снова: на **Beget** сентинелы `backups/.last_success` (39 ч) и `backups/tradein/.last_success` (38 ч) выглядят просроченными. Это хвосты, оставшиеся от переноса задач, — соответствующих строк в кроне Beget больше нет, и сторож их уже не проверяет. Удалить их стоит, иначе следующий, кто посмотрит, потратит время так же, как я. --- ## ⚠️ Caddy: механизм на месте, но переключён только наполовину — и у этого есть дата Проверял не конфиг, а что Caddy реально обслуживает (`caddy adapt` на живых контейнерах). | Хост | Обслуживаемые домены | |---|---| | **Beget** | `git`, `errors`, `obsidian`, `metrics` (+`garmin`) — **только инфраструктура, верно** | | **Poincare** | `gendsgn.ru`, `www`, `merahome`, `meraocenka`, `meraotsenka` **+ `git`, `errors`, `obsidian`, `metrics`** | Poincare тянет **оба** файла: `CADDY_SITES` там не задан, а дефолт в `Caddyfile:51` — `*`. По задумке так и есть («в окне на Selectel `CADDY_SITES=apps`»), то есть это не поломка, а невыполненный пока шаг окна. Сегодня это безвредно: DNS этих трёх доменов смотрит на Beget, трафик до Poincare не доходит. **Но сертификаты на Poincare уже лежат** — приехали вместе с данными — и у них есть сроки обновления: | Сертификат на Poincare | Окно обновления | |---|---| | `obsidian.gendsgn.ru` | **06–08.09.2026** | | `git.gendsgn.ru` | 12–14.09.2026 | | `metrics.gendsgn.ru` | 24–26.10.2026 | Через **одиннадцать дней** после окна Poincare начнёт обновлять сертификат домена, который живёт на другой машине: HTTP-01 пойдёт на Beget, проверка не пройдёт, и попытки будут повторяться — ровно тот сценарий с rate limit, о котором issue предупреждает. Само не рассосётся. Ставить `CADDY_SITES=apps` прямо сейчас не стал: боевой Caddy, неделя переезда, а выигрыш — устранение риска, который выстрелит не раньше 6 сентября. Это шаг окна, и в раннбуке ему место с явной датой-дедлайном, а не в списке «когда-нибудь». --- ## Обновление приёмки - [x] ~~Решён вопрос с Telegram~~ → **понижено до наблюдения**, бот работает, решение за владельцем без спешки - [x] **Crontab разведён** — проверено на обоих хостах, бэкапы идут - [ ] `Caddyfile` разведён по хостам — **на Beget сделано, на Poincare нет**; `CADDY_SITES=apps` в шаг окна, дедлайн 06.09 - [ ] Остальные пункты — без изменений, требуют владельца Мелочью: убрать на Beget осиротевшие сентинелы `backups/.last_success` и `backups/tradein/.last_success`.
Author
Owner

Проверил разделение CADDY_SITES заранее — работает, но нашёл один домен, который выпадает из схемы

Переключение запланировано на окно 30.08. Прогнал проверку сейчас, чтобы в окне под таймером не выяснять, что конфиг не собирается.

Текущее состояние прода

CADDY_SITES=* (дефолт), то есть Poincare грузит оба файла. Отсюда — сертификаты чужих доменов в его хранилище:

gendsgn.ru          www.gendsgn.ru
meraocenka.ru       www.meraocenka.ru
merahome.ru         www.merahome.ru
meraotsenka.ru      www.meraotsenka.ru
errors.gendsgn.ru   git.gendsgn.ru        ← инфраструктурные,
metrics.gendsgn.ru  obsidian.gendsgn.ru   ← живут на Beget
garmin.gendsgn.ru   ←

DNS всех пяти инфраструктурных проверил через 8.8.8.8 — все указывают на 46.173.16.127 (Beget). То есть Poincare держит и продлевает сертификаты для доменов, запросы по которым к нему не приходят вовсе. Ровно тот сценарий, ради которого переменная и заводилась.

Проверка конфига — все три режима валидны

Гонял caddy validate на боевом дереве конфигов, в одноразовом контейнере того же образа, только чтение, без reload:

CADDY_SITES результат
apps Valid configuration
infra Valid configuration
* (сегодняшний) Valid configuration

Значит разделение в окне не упрётся в синтаксис или недостающий сниппет.

Сверка покрытия — ни один домен из sites/ не теряется

файл домены
apps.caddy gendsgn.ru, www.gendsgn.ru, meraocenka.ru, merahome.ru, meraotsenka.ru + три www.mera* (добавлены сегодня в #3137)
infra.caddy git, errors, metrics, obsidian

Восемь плюс четыре — сходится с тем, что должно остаться на каждой стороне.

🟡 garmin.gendsgn.ru из этой схемы выпадает — и, похоже, уже сломан

Он не в sites/, а в untracked caddy/local/*.caddy, который Caddyfile импортирует безусловно, мимо CADDY_SITES. Само по себе разделение его не затронет.

Но замер показывает расхождение прямо сейчас:

  • сертификат на него держит Poincare — значит локальный блок лежит там;
  • DNS указывает на Beget;
  • https://garmin.gendsgn.ru/ отдаёт 404.

То есть запросы приходят на Beget, где блока нет, и упираются в catch-all. Похоже на хвост переезда продуктов на Poincare: блок уехал вместе с ними, а запись осталась.

Не трогал намеренно — это личный MCP-коннектор, и его защита построена на секрете в пути, который мне незачем брать в руки. Отмечаю, потому что в окне это всплывёт: после CADDY_SITES=apps на Poincare блок останется там же (импорт безусловный), и расхождение сохранится, пока не решится, на каком хосте домену жить.

## Проверил разделение `CADDY_SITES` заранее — работает, но нашёл один домен, который выпадает из схемы Переключение запланировано на окно 30.08. Прогнал проверку сейчас, чтобы в окне под таймером не выяснять, что конфиг не собирается. ### Текущее состояние прода `CADDY_SITES=*` (дефолт), то есть Poincare грузит **оба** файла. Отсюда — сертификаты чужих доменов в его хранилище: ``` gendsgn.ru www.gendsgn.ru meraocenka.ru www.meraocenka.ru merahome.ru www.merahome.ru meraotsenka.ru www.meraotsenka.ru errors.gendsgn.ru git.gendsgn.ru ← инфраструктурные, metrics.gendsgn.ru obsidian.gendsgn.ru ← живут на Beget garmin.gendsgn.ru ← ``` DNS всех пяти инфраструктурных проверил через 8.8.8.8 — **все указывают на 46.173.16.127 (Beget)**. То есть Poincare держит и продлевает сертификаты для доменов, запросы по которым к нему не приходят вовсе. Ровно тот сценарий, ради которого переменная и заводилась. ### Проверка конфига — все три режима валидны Гонял `caddy validate` на боевом дереве конфигов, в одноразовом контейнере того же образа, только чтение, без reload: | `CADDY_SITES` | результат | |---|---| | `apps` | **Valid configuration** | | `infra` | **Valid configuration** | | `*` (сегодняшний) | **Valid configuration** | Значит разделение в окне не упрётся в синтаксис или недостающий сниппет. ### Сверка покрытия — ни один домен из `sites/` не теряется | файл | домены | |---|---| | `apps.caddy` | `gendsgn.ru`, `www.gendsgn.ru`, `meraocenka.ru`, `merahome.ru`, `meraotsenka.ru` + три `www.mera*` (добавлены сегодня в #3137) | | `infra.caddy` | `git`, `errors`, `metrics`, `obsidian` | Восемь плюс четыре — сходится с тем, что должно остаться на каждой стороне. ### 🟡 `garmin.gendsgn.ru` из этой схемы выпадает — и, похоже, уже сломан Он не в `sites/`, а в untracked `caddy/local/*.caddy`, который `Caddyfile` импортирует **безусловно**, мимо `CADDY_SITES`. Само по себе разделение его не затронет. Но замер показывает расхождение прямо сейчас: - сертификат на него держит **Poincare** — значит локальный блок лежит там; - DNS указывает на **Beget**; - `https://garmin.gendsgn.ru/` отдаёт **404**. То есть запросы приходят на Beget, где блока нет, и упираются в catch-all. Похоже на хвост переезда продуктов на Poincare: блок уехал вместе с ними, а запись осталась. Не трогал намеренно — это личный MCP-коннектор, и его защита построена на секрете в пути, который мне незачем брать в руки. Отмечаю, потому что в окне это всплывёт: после `CADDY_SITES=apps` на Poincare блок останется там же (импорт безусловный), и расхождение сохранится, пока не решится, на каком хосте домену жить.
Author
Owner

Поправка к моему предыдущему комментарию: garmin.gendsgn.ru не сломан, решать нечего

Выше я записал его как расхождение между хостами и предложил решить, где ему жить. Проверил по-настоящему — расхождения нет, всё уже согласовано:

что где
контейнер garmin-mcp Beget, Up 9 days (healthy)
A-запись Beget (46.173.16.127)
site-блок caddy/local/garmin.caddy Beget, смонтирован в контейнер Caddy
сертификат Let's Encrypt Beget, /data/caddy/certificates/…/garmin.gendsgn.ru

Всё на одном хосте, и на том самом, куда смотрит DNS.

404 на корне — это замысел, а не поломка. Защита сервиса построена на секрете в пути (об этом прямо написано в комментарии к import caddy/local/*.caddy в Caddyfile). Голый https://garmin.gendsgn.ru/ обязан отдавать 404 — по адресу без секрета там ничего и не должно быть. Я принял это за отказ, потому что сравнивал с поведением обычного сайта.

Откуда взялось расхождение в моём замере: сертификат на garmin нашёлся и на Poincare — но это инертный остаток от переезда продуктов. Блока caddy/local/ на Poincare нет вовсе (каталог отсутствует), а Caddy продлевает только те домены, что есть в текущем конфиге. То есть этот сертификат просто лежит в томе и ничего не делает.

Действий не требуется. Пункт про garmin из списка вопросов снимаю.

Что при этом оказалось не зря

По ходу проверки заметил, что блок был в файле, но не в работающем конфиге — Caddy не перечитывал его с момента появления файла. Прогнал validate (Valid configuration), затем reload. После перезагрузки инфраструктурные домены проверены снаружи и целы:

git.gendsgn.ru       200
errors.gendsgn.ru    200
metrics.gendsgn.ru   302
obsidian.gendsgn.ru  401

Так что настоящий остаток по этому issue — прежний и единственный: пять инфраструктурных сертификатов на Poincare, которые он продлевает впустую, потому что грузит infra.caddy при CADDY_SITES=*. Их закрывает переключение в окне, и оно проверено (все три режима валидны).

## Поправка к моему предыдущему комментарию: `garmin.gendsgn.ru` не сломан, решать нечего Выше я записал его как расхождение между хостами и предложил решить, где ему жить. Проверил по-настоящему — расхождения нет, всё уже согласовано: | что | где | |---|---| | контейнер `garmin-mcp` | **Beget**, `Up 9 days (healthy)` | | A-запись | **Beget** (46.173.16.127) | | site-блок `caddy/local/garmin.caddy` | **Beget**, смонтирован в контейнер Caddy | | сертификат Let's Encrypt | **Beget**, `/data/caddy/certificates/…/garmin.gendsgn.ru` | Всё на одном хосте, и на том самом, куда смотрит DNS. **404 на корне — это замысел, а не поломка.** Защита сервиса построена на секрете в пути (об этом прямо написано в комментарии к `import caddy/local/*.caddy` в Caddyfile). Голый `https://garmin.gendsgn.ru/` обязан отдавать 404 — по адресу без секрета там ничего и не должно быть. Я принял это за отказ, потому что сравнивал с поведением обычного сайта. Откуда взялось расхождение в моём замере: сертификат на garmin нашёлся **и** на Poincare — но это инертный остаток от переезда продуктов. Блока `caddy/local/` на Poincare нет вовсе (каталог отсутствует), а Caddy продлевает только те домены, что есть в текущем конфиге. То есть этот сертификат просто лежит в томе и ничего не делает. **Действий не требуется.** Пункт про garmin из списка вопросов снимаю. ### Что при этом оказалось не зря По ходу проверки заметил, что блок был в файле, но **не в работающем конфиге** — Caddy не перечитывал его с момента появления файла. Прогнал `validate` (Valid configuration), затем `reload`. После перезагрузки инфраструктурные домены проверены снаружи и целы: ``` git.gendsgn.ru 200 errors.gendsgn.ru 200 metrics.gendsgn.ru 302 obsidian.gendsgn.ru 401 ``` Так что настоящий остаток по этому issue — прежний и единственный: **пять инфраструктурных сертификатов на Poincare**, которые он продлевает впустую, потому что грузит `infra.caddy` при `CADDY_SITES=*`. Их закрывает переключение в окне, и оно проверено (все три режима валидны).
Collaborator

Перепроверка 27.08.2026 (после пересборки базы 25-26.08 и переезда продукта на Poincare). Тело тикета писалось 20-24.08 по старой инфраструктуре.

Прокси-посылка не подтвердилась. Пул сейчас = 4 ASocks; mobileproxy.space, вокруг которого построено тело, в конфигурации отсутствует. Скрапинг Авито идёт (1174 строки за 3 суток) — то есть привязка к старому IP работу не рвёт.

Также в теле неверный адрес нового хоста: не 188.246.224.93, а 188.124.37.140.

Что реально остаётся: блокер Telegram с Selectel. Предлагаю переписать тикет под это, остальное снять.

**Перепроверка 27.08.2026** (после пересборки базы 25-26.08 и переезда продукта на Poincare). Тело тикета писалось 20-24.08 по старой инфраструктуре. Прокси-посылка **не подтвердилась**. Пул сейчас = 4 ASocks; `mobileproxy.space`, вокруг которого построено тело, в конфигурации отсутствует. Скрапинг Авито идёт (1174 строки за 3 суток) — то есть привязка к старому IP работу не рвёт. Также в теле неверный адрес нового хоста: не `188.246.224.93`, а `188.124.37.140`. **Что реально остаётся:** блокер Telegram с Selectel. Предлагаю переписать тикет под это, остальное снять.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3059
No description provided.