All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Метрик в проекте не было ни одной: ни экспортеров, ни /metrics в бэкендах, единственный канал наблюдения — journald, единственный сигнал об аварии — исключение в GlitchTip. Из-за этого целый класс отказов невидим в принципе: задача рапортует done, строк ноль, исключения нет. Так протухли данные на семь месяцев (#2998), 34 дня был мёртв house_imv_backfill (#2698), 8 суток писал ноль newbuilding_enrich (#2767), 91 день копилось раздутие listings (#2992). Grafana не заменяет GlitchTip: ошибки остаются там. Grafana OSS не принимает Sentry DSN ни одним компонентом, а скрубберы в before_send — требование 152-ФЗ. Здесь появляется другой класс данных: ряды и алерты по трендам. Наблюдатель поставлен у ДРУГОГО провайдера, чем наблюдаемое: серверная сторона на Beget, рядом с GlitchTip. Если ляжет Poincare, мониторинг должен об этом сказать, а не лечь вместе с ним. Транспорт push, а не pull: агент на Poincare шлёт remote_write и логи исходящим HTTPS, поэтому там не открывается ни одного входящего порта сверх 22/80/443. При обрыве канала Alloy копит в WAL и досылает — pull-скрейп в той же ситуации терял бы точки именно в аварии, ради которой мониторинг и нужен. Два контура доступа с разными учётками. Пароль приёмника по построению лежит открытым на продуктовом хосте, значит его компрометация неизбежна вместе с хостом; будь это учётка витрины, утёк бы и доступ к дашбордам. GlitchTip читается прямым SQL, а не Sentry-плагином: у плагина на 6.1.6 stats_v2 отдаёт 500 (баг GlitchTip #381), Events/Discover — 404 (#416), а в grafana/sentry-datasource слово glitchtip не встречается ни разу. Схема сверена на живой базе: колонка времени называется timestamp, а не received, и отдельной таблицы IssueIndex не существует — агрегаты лежат на самой issue_events_issue. Алерты за профилем alerts: канал доставки — открытый вопрос #3078, и стек не должен на нём стоять. Деплой предупреждает, что уведомлять пока некому. Каждая настройка, способная отказать молча, закрыта явно: ретенция Prometheus задана и по времени и по размеру, retention_enabled у компактора Loki (без него retention_period не работает вовсе), путь к журналу и запуск Alloy от root (иначе агент читает ноль записей без ошибки), проверка Caddy до перезагрузки (на этом хосте тот же Caddy держит git, errors и obsidian). Refs #3078
19 lines
1.5 KiB
Text
19 lines
1.5 KiB
Text
# Витрина мониторинга — внешний контур доступа к metrics.gendsgn.ru.
|
||
#
|
||
# Пароль живёт в окружении хоста как METRICS_UI_PASSWORD (backend/.env.runtime),
|
||
# сюда попадает только bcrypt-хеш — его публикация ничего не раскрывает.
|
||
# Сгенерирован ops/../scripts/setup-metrics-secrets.sh 2026-08-26.
|
||
#
|
||
# ЭТО ВТОРОЙ СЛОЙ, А НЕ ЕДИНСТВЕННЫЙ. У Grafana есть собственный вход с ролями
|
||
# (GF_USERS_ALLOW_SIGN_UP=false), и он остаётся включённым. Внешний basic_auth
|
||
# нужен потому, что дашборд смотрит в интернет: он отсекает сканеры и любую
|
||
# будущую дыру в самой Grafana до того, как она станет доступной снаружи.
|
||
# Если два запроса пароля подряд окажутся неудобны — убрать ОДНУ строку
|
||
# `import caddy/metrics-ui.caddy.snippet` из infra.caddy, вход Grafana останется.
|
||
#
|
||
# Формат: username base64(bcrypt_hash) # комментарий
|
||
# Caddy 2.11+ требует именно base64 от bcrypt-хеша.
|
||
|
||
basic_auth bcrypt "GenDesign Metrics" {
|
||
metrics JDJhJDE0JFpObUNJUzVGZnd3blRKQXE3cDIxVWVEaG1udjY0cHVyVmY3OE9Ga2xubjE5RC90elZkL0dD # витрина, пароль в METRICS_UI_PASSWORD на Beget
|
||
}
|