Some checks failed
CI Trade-In / changes (pull_request) Successful in 15s
CI / changes (pull_request) Successful in 20s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Failing after 1m39s
Без маршрута сервис tg-relay недостижим снаружи и настройка TELEGRAM_RELAY_BASE_URL на продуктовом хосте ни к чему не приводит. Путь несёт токен бота, поэтому помечен log_skip: иначе он осядет в файловом логе сайта и в stdout-копии, которую читает Alloy (#3154). Таймаут ответа поднят до 80с — getUpdates висит long-poll'ом до ~40с, дефолтного не хватает. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG
164 lines
9.4 KiB
Text
164 lines
9.4 KiB
Text
# ═══════════════════════════════════════════════════════════════════════════
|
||
# caddy/sites/infra.caddy — инфраструктурные домены, остающиеся на Beget
|
||
#
|
||
# Переезд GenDesign с Beget (46.173.16.127) на Selectel Poincare
|
||
# (188.124.37.140), окно 30.08.2026. Три домена этого файла ОСТАЮТСЯ на
|
||
# Beget — переезжают только Site Finder/МЕРА-домены (см.
|
||
# caddy/sites/apps.caddy). Общий механизм переключения (переменная
|
||
# CADDY_SITES, `import caddy/sites/{$CADDY_SITES:*}.caddy` в корневом
|
||
# Caddyfile, мотив с ACME rate-limit) описан в шапке apps.caddy — не
|
||
# дублируем здесь, читай там.
|
||
#
|
||
# Домены в этом файле (после переезда — на Beget, CADDY_SITES=infra):
|
||
# - obsidian.gendsgn.ru — Obsidian Self-hosted LiveSync (CouchDB backend)
|
||
# - errors.gendsgn.ru — GlitchTip, self-hosted error tracking
|
||
# - git.gendsgn.ru — Forgejo, self-hosted git + Actions CI
|
||
#
|
||
# На Selectel (CADDY_SITES=apps) этот файл не импортируется вообще — Caddy
|
||
# там даже не видит эти хосты и не пытается выпускать для них сертификаты.
|
||
# ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
# Obsidian Self-hosted LiveSync (CouchDB backend).
|
||
# Auto-TLS Let's Encrypt. CORS уже включён на стороне CouchDB через bootstrap
|
||
# (см. scripts/setup-couchdb.sh). Basic-auth — на стороне CouchDB (admin user).
|
||
#
|
||
# DNS: A-record obsidian.gendsgn.ru → IP VPS.
|
||
# Клиенты Obsidian + Self-hosted LiveSync plugin указывают на этот URL.
|
||
obsidian.gendsgn.ru {
|
||
encode zstd gzip
|
||
|
||
reverse_proxy couchdb:5984 {
|
||
# Большие документы (vault attachments / images) — увеличиваем timeout
|
||
transport http {
|
||
response_header_timeout 120s
|
||
}
|
||
}
|
||
}
|
||
|
||
# GlitchTip — self-hosted error tracking (Sentry-compatible).
|
||
# DNS: A-record errors.gendsgn.ru → IP VPS.
|
||
errors.gendsgn.ru {
|
||
encode zstd gzip
|
||
|
||
reverse_proxy glitchtip-web:8080
|
||
|
||
log {
|
||
output file /var/log/caddy/errors.gendsgn.ru.log
|
||
}
|
||
}
|
||
|
||
# Forgejo — self-hosted git (migration 2026-05-16).
|
||
# DNS: A-record git.gendsgn.ru → IP VPS.
|
||
# Forgejo container из forgejo-migration/docker-compose.yml на shared
|
||
# gendesign_default network. HTTP port 3000 (default Forgejo).
|
||
# Был добавлен вручную при migration, потерян при первом auto-deploy после
|
||
# изменения Caddyfile (deploy.yml делает git reset --hard). См. fix issue.
|
||
git.gendsgn.ru {
|
||
encode zstd gzip
|
||
|
||
reverse_proxy forgejo:3000
|
||
|
||
log {
|
||
output file /var/log/caddy/git.gendsgn.ru.log
|
||
}
|
||
}
|
||
|
||
# Мониторинг — Grafana + приёмник метрик и логов (задача #3078).
|
||
# DNS: A-record metrics.gendsgn.ru → 46.173.16.127 (заведена 2026-08-26).
|
||
#
|
||
# ПОЧЕМУ ЗДЕСЬ, А НЕ В apps.caddy. Наблюдатель сознательно поставлен у ДРУГОГО
|
||
# провайдера, чем наблюдаемое: продукт живёт на Selectel Poincare, и если ляжет
|
||
# он, мониторинг обязан выжить и сказать об этом. Стек поднимается отдельным
|
||
# compose-проектом gendesign-metrics и виден Caddy через сеть gendesign_shared.
|
||
#
|
||
# ДВА КОНТУРА С РАЗНЫМИ УЧЁТКАМИ:
|
||
# /ingest/* — машинный. Агент Alloy с Poincare шлёт сюда remote_write и логи
|
||
# исходящим HTTPS. Благодаря этому на Poincare не открыт НИ ОДИН
|
||
# входящий порт сверх 22/80/443.
|
||
# всё прочее — витрина Grafana под отдельным паролем.
|
||
# Пароль приёмника по построению лежит в открытом виде на продуктовом хосте;
|
||
# разделив учётки, мы не отдаём вместе с ним доступ к дашбордам.
|
||
metrics.gendsgn.ru {
|
||
encode zstd gzip
|
||
|
||
# handle_path срезает префикс: Prometheus получает /api/v1/write,
|
||
# как если бы обращались к нему напрямую.
|
||
handle_path /ingest/prometheus/* {
|
||
import ../metrics-ingest.caddy.snippet
|
||
reverse_proxy prometheus:9090
|
||
}
|
||
|
||
# Loki ожидает путь /loki/api/v1/push — он и остаётся после среза /ingest/loki.
|
||
handle_path /ingest/loki/* {
|
||
import ../metrics-ingest.caddy.snippet
|
||
reverse_proxy loki:3100
|
||
}
|
||
|
||
# Кнопка «Принял в работу» под клиентским инцидентом (#3078).
|
||
#
|
||
# БЕЗ АВТОРИЗАЦИИ НАМЕРЕННО. Кнопку жмут с телефона, ночью, когда лежит
|
||
# прод. Требовать в этот момент ввод пароля — значит получить ноль нажатий
|
||
# и вернуться к вопросу «а кто-нибудь вообще это читает».
|
||
#
|
||
# Защита — неугадываемость и одноразовость: путь содержит 128-битный токен,
|
||
# выданный ровно под это сообщение и живущий сутки. Худшее, чего добьётся
|
||
# угадавший, — ложная отметка «принято» в чате, где сразу видно, что её
|
||
# поставил не человек. Прав в системе токен не даёт никаких.
|
||
#
|
||
# Сервис отвечает только на /ack/*, /glitchtip и /healthz; всё прочее — 404.
|
||
handle /ack/* {
|
||
reverse_proxy alert-ack:8080
|
||
}
|
||
|
||
# Резервный приёмник алертов GlitchTip (#3471). Основной получатель —
|
||
# продуктовый бэкенд на Selectel, то есть тот самый сервис, за которым эти
|
||
# алерты и следят: пока он лежит, его собственные ошибки доставлять некому.
|
||
# Этот путь живёт у другого провайдера и с чистой сетью до Telegram, поэтому
|
||
# переживает падение Selectel целиком.
|
||
#
|
||
# Секрет — в значении query-параметра, а не в пути: путь сам по себе не
|
||
# секрет, и его попадание в access-лог безопасно. Само значение вырезает
|
||
# scrub_credentials в Alloy до записи в Loki (#3154).
|
||
handle /glitchtip* {
|
||
reverse_proxy alert-ack:8080
|
||
}
|
||
|
||
# Ретранслятор Bot API продукта (#3471). Путь от Selectel до
|
||
# api.telegram.org теряет примерно каждый четвёртый короткий запрос, тот же
|
||
# замер с Beget в те же минуты — чистый. Поэтому продуктовый бот ходит в
|
||
# Telegram отсюда, а не напрямую.
|
||
#
|
||
# Путь содержит токен бота (/tg-relay/bot<TOKEN>/<method>) — он не должен
|
||
# осесть ни в файловом логе сайта, ни в stdout-копии (#3154), поэтому
|
||
# запрос помечен log_skip.
|
||
@tg_relay path /tg-relay/*
|
||
log_skip @tg_relay
|
||
|
||
handle_path /tg-relay/* {
|
||
reverse_proxy tg-relay:8080 {
|
||
# getUpdates — long-poll до ~40с, дефолтный таймаут ответа короче.
|
||
transport http {
|
||
response_header_timeout 80s
|
||
}
|
||
}
|
||
}
|
||
|
||
# Вход ОДИН — собственный вход Grafana (#3078). Внешний basic_auth снят по
|
||
# решению владельца: два запроса пароля подряд мешали работе, а Grafana имеет
|
||
# собственную аутентификацию с ролями и `GF_USERS_ALLOW_SIGN_UP=false`.
|
||
#
|
||
# Что при этом теряется, чтобы решение было осознанным: basic_auth отсекал
|
||
# сканеры до Grafana и прикрывал бы её собственную будущую уязвимость. Теперь
|
||
# страница входа Grafana видна из интернета напрямую.
|
||
#
|
||
# Приём метрик НАРОЧНО остаётся под basic_auth (см. handle_path выше): туда
|
||
# ходит агент по паролю, который лежит в открытом виде в окружении
|
||
# продуктового хоста, и отдельная учётка там ограничивает ущерб записью.
|
||
handle {
|
||
reverse_proxy grafana:3000
|
||
}
|
||
|
||
log {
|
||
output file /var/log/caddy/metrics.gendsgn.ru.log
|
||
}
|
||
}
|