All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Внешний basic_auth Caddy снят с витрины по решению владельца: два запроса пароля подряд мешали работе, а у Grafana есть собственная аутентификация с ролями и GF_USERS_ALLOW_SIGN_UP=false. Что теряется, чтобы решение было осознанным: basic_auth отсекал сканеры до Grafana и прикрыл бы её собственную будущую уязвимость. Теперь страница входа видна из интернета напрямую. Это записано комментарием прямо в конфиге, чтобы через полгода не выглядело недосмотром. Приём метрик НАРОЧНО остаётся под basic_auth: туда ходит агент по паролю, который лежит в открытом виде в окружении продуктового хоста, и отдельная учётка там ограничивает ущерб записью. Снят ровно один слой и ровно с витрины. Файл metrics-ui.caddy.snippet и его bind-mount оставлены на месте: диффу так меньше, вернуть слой можно одной строкой. Гард импортов (#3104) проверяет обратное направление - что каждый import покрыт маунтом, - поэтому лишний маунт его не трогает. Проверено: scripts/check-caddy-snippet-mounts.py зелёный (6 конфигов, 7 маунтов); конфиг с новой версией infra.caddy проходит caddy validate в одноразовом контейнере на Beget - Valid configuration.
115 lines
6.3 KiB
Text
115 lines
6.3 KiB
Text
# ═══════════════════════════════════════════════════════════════════════════
|
||
# caddy/sites/infra.caddy — инфраструктурные домены, остающиеся на Beget
|
||
#
|
||
# Переезд GenDesign с Beget (46.173.16.127) на Selectel Poincare
|
||
# (188.246.224.93), окно 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
|
||
}
|
||
|
||
# Вход ОДИН — собственный вход 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
|
||
}
|
||
}
|