Конфигурация

Gotcha полностью настраивается переменными окружения с префиксом GOTCHA_. Ни одного конфиг-файла, ни одной настройки через веб-интерфейс для системных параметров — только переменные окружения. Их авторитетный источник — файл cmd/gotcha/config.go в исходном коде; этот документ — читаемое описание того же самого, сгруппированное по смыслу. Шаблон со всеми переменными и комментариями лежит в .env.example в корне репозитория.

Конвенция именования переменных

Числовая переменная несёт единицу измерения прямо в имени: _SECONDS, _DAYS, _HOURS, _BYTES, _PER_SEC, _PER_MIN (например GOTCHA_ESCALATION_INTERVAL_SECONDS, GOTCHA_EXPORT_RETENTION_HOURS, GOTCHA_DIST_RATE_PER_MIN). Голое число без единицы в имени неоднозначно — шестьдесят чего именно, секунд или минут? Для сроков хранения (retention) в имени называется ещё и вид данных, который отсекается (GOTCHA_EVENT_RETENTION_DAYS, GOTCHA_LOG_RETENTION_DAYS, GOTCHA_DEPLOY_RETENTION_DAYS), а не общий RETENTION_DAYS на всё сразу. Префикс переменной называет подсистему, а не продукт целиком: GOTCHA_AGENT_* — только процесс агента на хосте (gotcha-agent), отдельный бинарь; GOTCHA_DIST_* — раздачу инстансом бинарей агента (не сам агент); GOTCHA_PROBE_* — выносную пробу (--mode=probe). Невалидное значение любой переменной — отказ старта процесса, а не тихий откат к дефолту: опечатка в конфигурации обязана быть замечена оператором сразу, а не спустя недели молчаливо неверного поведения.

Конвенцию единиц измерения проверяет тест internal/guards/env_example_test.go: подозрительна ЛЮБАЯ переменная, прочитанная в cmd/gotcha/config.go или internal/agent/config.go как голое число (intNum/num) без нужного суффикса в имени — гейт валит её, если она не перечислена явно в закрытом списке unitlessCounters того же теста (счётчики штук вроде лимитов, конкурентности и порта, у которых единицы измерения нет и быть не может). Добавление новой строки в этот список — заметная в код-ревью правка, а не тихий обход конвенции.

Отдельно от значения — само ИМЯ переменной тоже проверяется при старте. GOTCHA_*, которую не читает ни cmd/gotcha, ни internal/agent (реестр известных имён — internal/envcontract/known.go, объединение серверных и агентских переменных: агент штатно ставится на тот же хост, что и сервер, с общим .env), отказывает старту с подсказкой ближайшего известного имени (расстояние Левенштейна не больше двух) — опечатка вроде GOTCHA_HSTS_ENABLE (без D) больше не проходит молча с дефолтом. Исключение — префиксы GOTCHA_COMPOSE_* и GOTCHA_BUILD_*: их читает сам Docker Compose (подстановка ${...}) или Makefile (build-args образа), ни один Go-процесс их не читает, и в реестр известных имён они не входят.

Как задать переменные окружения в Docker Compose

Два равнозначных способа:

Способ 1 — файл .env рядом с docker-compose.yml (рекомендуется, самый простой). Docker Compose читает его автоматически:

# в папке gotcha/
nano .env
GOTCHA_SECRET_KEY=случайная-строка-из-openssl-rand
GOTCHA_BASE_URL=https://gotcha.example.com
GOTCHA_SMTP_HOST=smtp.yandex.ru
GOTCHA_SMTP_PORT=465
GOTCHA_SMTP_USER=noreply@example.com
GOTCHA_SMTP_PASSWORD=пароль-приложения
GOTCHA_SMTP_FROM=noreply@example.com

Применить изменения:

docker compose up -d

(команда пересоздаёт контейнер gotcha с новыми переменными; postgres/clickhouse не трогает, если их переменные не менялись).

Способ 2 — блок environment: прямо в docker-compose.yml. Если вы не хотите заводить .env, можно прописать переменные прямо в compose-файле, в секции сервиса gotcha:

services:
  gotcha:
    # ...
    environment:
      GOTCHA_PG_DSN: postgres://gotcha:gotcha@postgres:5432/gotcha?sslmode=disable
      GOTCHA_CH_DSN: clickhouse://gotcha:gotcha@clickhouse:9000/gotcha
      GOTCHA_BASE_URL: ${GOTCHA_BASE_URL:-http://localhost:59080}
      GOTCHA_SECRET_KEY: ${GOTCHA_SECRET_KEY:-insecure-dev-secret}
      GOTCHA_SMTP_HOST: smtp.yandex.ru

${VAR:-default} — это подстановка Docker Compose: «взять значение VAR из окружения/.env, а если не задано — использовать значение после :-». В штатном docker-compose.yml репозитория уже используется этот приём для GOTCHA_BASE_URL и GOTCHA_SECRET_KEY, так что для этих двух переменных обычно достаточно способа 1 (просто создать .env), ничего не редактируя в самом compose-файле.

После любого изменения переменных выполните docker compose up -d, чтобы применить их — Docker Compose сам обнаружит, что конфигурация контейнера изменилась, и пересоздаст его.


Core (основные)

ПеременнаяПо умолчаниюОписание
GOTCHA_LISTEN_ADDR:8080Адрес и порт, который слушает HTTP-сервер внутри контейнера. Как правило, менять не нужно — наружу порт пробрасывается через docker-compose.yml/GOTCHA_COMPOSE_PORT (см. Установку), а не через эту переменную.
GOTCHA_BASE_URLhttp://localhost:8080Публичный адрес вашего инстанса — то, как до него реально добираются пользователи и SDK. Используется для построения DSN проектов, ссылок в письмах-приглашениях и ссылок на инциденты в алертах (Telegram/webhook/email). Должен точно совпадать со схемой+хостом+портом, по которым инстанс реально доступен. Если значение не localhost/127.0.0.1, приложение в режимах web, all, ingest и uptime (везде, кроме probe) требует не-дефолтный GOTCHA_SECRET_KEY — см. раздел Security ниже. Если значение не начинается с https:// и не локальное — в лог пишется предупреждение (сессионные cookie идут открытым текстом).
GOMEMLIMIT(вычисляется из cgroup)Стандартная (без префикса GOTCHA_) переменная самого Go-рантайма — потолок кучи. Оставленная незаданной, читается напрямую internal/memlimit, который в контейнере сам выводит её из потолка cgroup (см. «Переменные только для Compose» ниже, GOTCHA_COMPOSE_MEM_LIMIT); задавайте вручную только на bare metal без cgroup или чтобы переопределить выведенное значение.

Database (база данных)

ПеременнаяПо умолчаниюОписание
GOTCHA_PG_DSNpostgres://gotcha:gotcha@localhost:5432/gotcha?sslmode=disableСтрока подключения к PostgreSQL — хранит организации, проекты, пользователей, правила алертов, инциденты. В штатном docker-compose.yml уже выставлено postgres://gotcha:gotcha@postgres:5432/gotcha?sslmode=disable (имя хоста postgres — это имя сервиса в docker-сети). Менять нужно, только если вы используете внешнюю/собственную БД вместо контейнера из compose. Значение обрезается по краям; строка из одних пробелов — отказ старта (а не тихий откат на дефолтный localhost-DSN). Разбираемость DSN (URL-форма или keyword/value-форма, обе законны) проверяется на старте — опечатка отказывает запуск сразу, а не на первом подключении к БД.
GOTCHA_CH_DSNclickhouse://localhost:9000/gotchaСтрока подключения к ClickHouse — хранит события, спаны трейсов, метрики, профили, результаты аптайм-проверок. В штатном compose — clickhouse://gotcha:gotcha@clickhouse:9000/gotcha. Менять по тем же причинам, что и GOTCHA_PG_DSN. Тот же тримминг, тот же отказ старта на пробельном значении и та же проверка разбираемости на старте.

Переменные только для compose (контейнеры баз)

Эти четыре — переменные подстановки Docker Compose, а не конфигурация процесса gotcha: приложение их не читает. Compose подставляет их в настройки контейнеров баз и в DSN выше.

ПеременнаяПо умолчаниюОписание
GOTCHA_COMPOSE_PG_PASSWORDgotchaПароль пользователя gotcha в PostgreSQL. Подставляется и в контейнер postgres (POSTGRES_PASSWORD), и в GOTCHA_PG_DSN приложения. Символы, требующие URL-экранирования (@ / : # %), использовать нельзя — значение попадает в DSN-URL как есть.
GOTCHA_COMPOSE_CH_PASSWORDgotchaПароль пользователя gotcha в ClickHouse. Та же механика и то же ограничение на символы, что у GOTCHA_COMPOSE_PG_PASSWORD.
GOTCHA_COMPOSE_PG_MEM_LIMIT512mПотолок памяти контейнера postgres. На сервере с запасом — поднять.
GOTCHA_COMPOSE_CH_MEM_LIMIT2gПотолок памяти контейнера clickhouse. Без cgroup-лимита ClickHouse считает своими 90% памяти хоста — именно потолок делает его бюджет памяти реальным.

Смена пароля базы на живой установке. POSTGRES_PASSWORD/CLICKHOUSE_PASSWORD действуют только при первичной инициализации тома — на живой установке смена одной переменной запирает приложение перед базой, которая ждёт старый пароль. Порядок важен:

  1. Сменить пароль в самой базе:
    docker compose exec postgres psql -U gotcha -d gotcha -c "ALTER USER gotcha WITH PASSWORD 'новый-пароль'"
    docker compose exec clickhouse clickhouse-client --user gotcha --password 'старый-пароль' -q "ALTER USER gotcha IDENTIFIED BY 'новый-пароль'"
    
  2. Задать GOTCHA_COMPOSE_PG_PASSWORD/GOTCHA_COMPOSE_CH_PASSWORD в .env.
  3. docker compose up -d — контейнер приложения пересоздаётся с новым DSN.

Переменные только для Compose (контейнер приложения)

ПеременнаяПо умолчаниюОписание
GOTCHA_COMPOSE_MEM_LIMIT1gПотолок памяти контейнера gotcha. Приложение читает лимит из cgroup и само выставляет потолок кучи в 80% от него, поэтому достаточно поднять потолок — GOMEMLIMIT руками задавать не нужно.
GOTCHA_COMPOSE_NET_MTU1500MTU сети контейнеров. Средство от одной конкретной поломки, описанной ниже; само по себе расхождение MTU — не повод сюда лезть.
GOTCHA_COMPOSE_BIND127.0.0.1Адрес хоста, на который публикуется порт приложения. По умолчанию — только loopback: снаружи сервера порт недоступен, пока вы явно не зададите 0.0.0.0 (см. Установку).
GOTCHA_COMPOSE_PORT59080Порт хоста, на который публикуется контейнер приложения (порт 8080 внутри контейнера не меняется). Смените, если 59080 на хосте уже занят другим сервисом.

Переменные только для сборки (build-args Makefile)

Эти три — тоже переменные подстановки, но не Docker Compose, а Makefile: он передаёт их дальше в docker compose build как build-args образа (DOCKER_BUILD_ENV, см. Dockerfile). Ни один процесс gotcha их не читает; сборка make задаёт их сама (git describe/коммит/дата) — эти переменные нужны, только если вы собираете образ через docker compose build напрямую, в обход make.

ПеременнаяПо умолчаниюОписание
GOTCHA_BUILD_VERSIONdevВерсия, которую бинарник печатает в /healthz и логе старта. make задаёт её сама из git describe --tags.
GOTCHA_BUILD_COMMIT(пусто)Хеш коммита, зашиваемый в бинарник тем же путём.
GOTCHA_BUILD_DATE(пусто)Дата сборки, зашиваемая в бинарник тем же путём.

Отталкиваться от симптома, а не от чисел. Docker даёт сети контейнеров MTU 1500, не глядя на аплинк хоста, а у VPS за туннелем (GRE, VXLAN, OpenVZ) он сплошь и рядом 1450. Само по себе расхождение встречается повсеместно, и большинство установок живут с ним, ничего не замечая.

Но безвредно оно только в одну сторону. Исходящие пакеты чинит своё же ядро: узкое звено — собственный интерфейс хоста, ядро сообщает об этом контейнеру, тот понижает MTU маршрута. Входящие зависят от удалённой стороны: она шлёт сегменты того размера, который контейнер объявил при установке соединения (MSS = MTU − 40, то есть 1460 вместо 1410), и уменьшит их, только если получит ICMP «fragmentation needed» от узла на пути. Дойдёт ли этот ICMP — не ваша сторона и не ваш контроль. Если его режут, отправитель продолжает слать по 1460 байт, и они пропадают.

Отсюда все признаки этой поломки:

  • мелкие обмены идут, крупные пропадают: TCP устанавливается, приветствие SMTP 220 приходит, а TLS-хендшейк — первый крупный обмен — виснет по таймауту;
  • разные адресаты ведут себя по-разному: до одного хоста TLS проходит, до другого нет, потому что ICMP режут не везде;
  • может работать, а потом перестать: ядро держит выученный PMTU в кэше маршрута около десяти минут (net.ipv4.route.mtu_expires), и пока запись жива, всё в порядке — после протухания симптом возвращается сам;
  • с хоста то же самое работает всегда: там интерфейс 1450, и MSS сразу объявляется 1410, никакого ICMP не требуется.

Последний пункт — главная ловушка при диагностике. Проверять надо изнутри контейнера, а не с хоста:

docker compose exec gotcha wget -q -O /dev/null https://api.github.com/ && echo ok || echo fail

Если отсюда TLS виснет, а с хоста openssl s_client -starttls smtp -connect <ваш-smtp>:587 проходит целиком — дело именно в MTU.

Этим же путём идёт всё исходящее — почта, вебхуки, OAuth и HTTP-проверки аптайма, — поэтому, когда это всё-таки случается, наблюдаемый сайт может числиться недоступным из-за MTU контейнера, который за ним наблюдает.

Проверка на хосте:

ip -o link show

Если у внешнего интерфейса (ens3, eth0) MTU меньше 1500, у docker0 — 1500, и при этом наблюдается описанный таймаут, задайте GOTCHA_COMPOSE_NET_MTU равным значению интерфейса и поднимите стек заново. Тогда контейнер объявляет MSS, который путь заведомо вывозит, и доставка перестаёт зависеть от чужого ICMP:

docker compose down && docker compose up -d

Именно down, а не один up -d: смена значения требует пересоздания сети, и если делать это под работающими контейнерами, встроенный DNS Docker остаётся с прежними записями — сервисы перестают находить друг друга по имени (lookup postgres on 127.0.0.11:53: server misbehaving), пока стек не поднимут целиком.

Если доставка не восстановилась — дело было не в MTU: верните значение обратно и разбирайтесь с достижимостью (Оповещения проводят по шагам).

Email / SMTP

Используется для писем-приглашений и email-канала алертов. Пока GOTCHA_SMTP_HOST пуст — отправка почты выключена целиком (в логах будет предупреждение GOTCHA_SMTP_HOST is not set, email alert channels are disabled), при этом остальная функциональность работает нормально.

ПеременнаяПо умолчаниюОписание
GOTCHA_SMTP_HOST(пусто)Адрес SMTP-сервера, например smtp.yandex.ru. Пока пусто — почта выключена.
GOTCHA_SMTP_PORT587Порт SMTP. 587 (STARTTLS) — обычный выбор; некоторые провайдеры используют 465 (SMTPS). Допустимый диапазон — 1..65535; значение вне него — отказ старта, а не отложенная ошибка при первой отправке письма.
GOTCHA_SMTP_USER(пусто)Логин для авторизации на SMTP-сервере.
GOTCHA_SMTP_PASSWORD(пусто)Пароль. Для сервисов вроде Яндекс/Gmail обычно нужен не пароль от аккаунта, а отдельный «пароль приложения».
GOTCHA_SMTP_FROM(пусто)Адрес отправителя в заголовке From: писем.

Telegram

ПеременнаяПо умолчаниюОписание
GOTCHA_TELEGRAM_API_BASE(пусто — https://api.telegram.org)Базовый адрес Bot API. Задайте, если инстанс не достаёт до api.telegram.org: фильтрация трафика по пути, закрытый исход из периметра, собственный сервер telegram-bot-api. Требуется абсолютный http(s)-адрес без запроса и фрагмента — отправитель дописывает /bot{token}/sendMessage; невалидное значение останавливает запуск, а не превращается в таймаут на каждой доставке.

Исходящий прокси для Telegram задаётся стандартными переменными HTTPS_PROXY/HTTP_PROXY/NO_PROXY. На webhook-каналы, OAuth и проверки аптайма он не распространяется: они намеренно ходят к цели напрямую, потому что SSRF-фильтр решает по фактическому адресу соединения, а прокси унёс бы это решение за пределы инстанса. Диагностика Telegram — в разделе Оповещения.

Retention (хранение данных ClickHouse)

Сколько дней ClickHouse хранит данные каждого типа, прежде чем удалить старые записи. Меньше — меньше места на диске, больше — глубже история для расследований.

ПеременнаяПо умолчаниюОписание
GOTCHA_EVENT_RETENTION_DAYS90Хранение событий (ошибок), транзакций и Web Vitals, а также описывающих их сводных записей в PostgreSQL: групп ошибок, групп производительности и регрессий производительности (см. Приватность). Прочие сводные записи живут сроком СВОЕЙ телеметрии: инциденты метрик — GOTCHA_METRIC_RETENTION_DAYS, регрессии профилей — GOTCHA_PROFILE_RETENTION_DAYS, закрытые инциденты аптайма — GOTCHA_INCIDENT_RETENTION_DAYS. Этим же сроком живут результаты проверок аптайма (check_results), поэтому значение меньше 90 укорачивает и историю публичной статус-страницы: она показывает не больше этого числа дней (обычно — 90). 0 — хранить бессрочно: TTL в ClickHouse снимается, по возрасту ничего не удаляется.
GOTCHA_SPAN_RETENTION_DAYS30Хранение спанов трейсов (детали внутри транзакций). 0 — хранить бессрочно.
GOTCHA_METRIC_RETENTION_DAYS30Хранение точек метрик (принятых по OTLP). 0 — хранить бессрочно.
GOTCHA_PROFILE_RETENTION_DAYS7Хранение сэмплов профилирования (самые тяжёлые по объёму данные, поэтому дефолт короче остальных). 0 — хранить бессрочно.
GOTCHA_LOG_RETENTION_DAYS14Хранение структурных логов (принятых по OTLP или NDJSON — см. Логи). Логи объёмнее событий, поэтому дефолт короче. 0 — хранить бессрочно.
GOTCHA_INCIDENT_RETENTION_DAYS90Хранение ЗАКРЫТЫХ инцидентов аптайма в PostgreSQL. Своя переменная, а не общая с событиями: у инцидента аптайма нет собственной телеметрии в ClickHouse (результаты проверок живут отдельным сроком), зато его показывает публичная статус-страница, обещающая историю за девяносто дней. Открытые инциденты не удаляются никогда. 0 — хранить закрытые инциденты бессрочно.
GOTCHA_DEPLOY_RETENTION_DAYS90Хранение маркеров выкладок в PostgreSQL. Своя переменная, а не общая с событиями: история выкладок — отдельная ось, не привязанная к телеметрии в ClickHouse, а таблицу пишет публичный ключ приёма (CI шлёт деплой тем же DSN) вне квоты, поэтому граница обязательна. 0 — хранить выкладки бессрочно.
GOTCHA_PROJECT_PURGE_RECONCILE_HOURS24Как часто искать в ClickHouse телеметрию проектов, которых больше нет, и ставить её в очередь на удаление. Удаление проекта ставит заявку само — той же транзакцией, что удаляет строку, — а сверка нужна на случай, когда заявки не появилось вовсе: падение до фиксации транзакции, ручная правка строк, данные, оставшиеся от прежних версий. 0 выключает сверку: это нужно установке, где в тот же ClickHouse пишет что-то помимо gotcha.
GOTCHA_OUTBOX_RETENTION_DAYS7Хранение записей об уже доставленных/провалившихся уведомлениях (email/webhook/Telegram) в PostgreSQL. Значение специально небольшое: это рабочая очередь, а не архив: она живёт в PostgreSQL и растёт вместе с числом уведомлений. Минимум 1 — 0 отвергается на старте.

Изменение retention применяется на следующем старте приложения (значение используется, чтобы выставить TTL на таблицах ClickHouse) — задним числом уже удалённые данные не восстановятся.

Quotas & edition (квоты и редакция)

ПеременнаяПо умолчаниюОписание
GOTCHA_EDITIONossoss или saas, без учёта регистра (OSS/SaaS тоже принимаются). Определяет дефолт для квот ниже: в oss все дефолты = 0 (безлимит), в saas = 1 000 000 в месяц. Явно заданный GOTCHA_DEFAULT_*_QUOTA всегда перекрывает дефолт редакции.
GOTCHA_DEFAULT_EVENT_QUOTA0 в ossДефолтная месячная квота на приём событий (ошибок) для новых организаций. 0 = безлимит.
GOTCHA_DEFAULT_TRANSACTION_QUOTA0 в ossТо же для транзакций (performance-трейсов).
GOTCHA_DEFAULT_METRIC_QUOTA0 в ossТо же для точек метрик.
GOTCHA_DEFAULT_PROFILE_QUOTA0 в ossТо же для профилей.
GOTCHA_DEFAULT_LOG_QUOTA0 в ossТо же для логов.
GOTCHA_MAX_EVENT_BYTES1048576 (1 МиБ)Максимальный размер одного принимаемого события в байтах. Событие крупнее — отклоняется.
GOTCHA_INGEST_RATE_PER_SEC500Per-DSN лимит приёма: запросов в секунду на проект (токен-бакет, burst = 2×лимит). Проверяется после аутентификации DSN и до квот; сверх лимита API отвечает 429 с коротким Retry-After. 0 отключает лимит.
GOTCHA_MAX_WRITER_BUFFER_BYTESавто (см. ниже)Байтовый потолок КАЖДОГО буфера писателя в ClickHouse (события, спаны, метрики, профили, логи). Буферы растут, пока ClickHouse недоступен, — так телеметрия не теряется на коротком сбое; потолок ограничивает эту плату. Заданное здесь число всегда побеждает авто-поведение. Результаты аптайм-проверок буферизуются отдельно и ограничены по числу строк (10000), а не этой переменной. Незаданная переменная включает авто-поведение; явные 0 и отрицательное число — ошибка конфигурации, отказ старта.
GOTCHA_MAX_INGEST_QUEUE_BYTES67108864 (64 МиБ)Байтовый потолок очереди приёма — в дополнение к её ёмкости в 1000 задач. Одно событие несёт до четырёх сырых JSON-блоков по 256 КиБ, то есть до мегабайта, и без этого потолка очередь могла удерживать порядка гигабайта. При исчерпании событие отбрасывается со счётчиком gotcha_pipeline_dropped_tasks_total; текущий объём виден в gotcha_pipeline_queue_bytes. Незаданная переменная берёт дефолт выше; явные 0 и отрицательное число — ошибка конфигурации, отказ старта.

Авто-дефолт GOTCHA_MAX_WRITER_BUFFER_BYTES: если переменная не задана, потолок каждого буфера-писателя выводится из обнаруженного потолка кучи (того же 80%-от-GOTCHA_COMPOSE_MEM_LIMIT потолка, описанного выше в «Переменные только для Compose»), а не берётся flat-константой пакета (256 МиБ). Буферов-«единиц» шесть (событие, спаны-транзакций и спаны-детей у трейсинга — два независимых буфера одного писателя, метрики, профили, логи); авто-дефолт делит на них 60% потолка кучи, оставляя 40% на всё остальное (HTTP-приём, парсер JSON, клиент PostgreSQL, сам рантайм). На дефолтном docker-compose.yml (mem_limit: 1g, потолок кучи ≈ 819 МиБ) это даёт около 82 МиБ на буфер — вместо flat 256 МиБ, которые суммарно (1.5 ГиБ) превышали бы потолок кучи и на длительном простое ClickHouse могли привести к OOM ядра. Если потолок кучи вывести не из чего (bare-metal без cgroup и без GOMEMLIMIT) — поведение прежнее, flat 256 МиБ на буфер. Явно заданный GOTCHA_MAX_WRITER_BUFFER_BYTES всегда побеждает авто-дефолт — в том числе для стеснённых профилей (docker-compose.small.yml продолжает задавать 24 МиБ явно).

Когда обязательно менять квоты: значения 0 (безлимит) в oss-редакции — это сознательный выбор для приватного self-hosted инстанса, где DSN не утекает наружу. Если DSN проекта попадает в публично доступный код (например, во фронтенд-JS вашего сайта), кто угодно может слать на него события неограниченно — это и вектор злоупотребления, и риск исчерпать диск ClickHouse. В таком случае задайте реальные числа, например:

GOTCHA_DEFAULT_EVENT_QUOTA=100000
GOTCHA_DEFAULT_TRANSACTION_QUOTA=50000

(Это дефолт для новых организаций; квоту существующей организации можно изменить в её настройках в веб-интерфейсе.)

Privacy / scrubbing (приватность)

Серверная очистка персональных данных перед сохранением — включена по умолчанию.

ПеременнаяПо умолчаниюОписание
GOTCHA_SCRUB_IPtrueЗануляет IP-адрес пользователя, о котором сообщило событие, перед сохранением.
GOTCHA_SCRUB_EMAILtrueЗануляет email пользователя, о котором сообщило событие, перед сохранением.
GOTCHA_SCRUB_DENY_KEYSвстроенный список (password,passwd,pwd,pass,token,secret,authorization,auth,cookie,api_key,apikey,access_token,refresh_token,session,credit_card,card_number,cvv)Список ключей (через запятую, без учёта регистра), значения которых маскируются в тегах/контекстах/стек-трейсах/данных спанов. Переменная дополняет встроенный список, а не заменяет его: добавить свой ключ (например, internal_user_id) можно одним значением, не перечисляя стандартные. Убрать конкретный встроенный ключ — точным именем через GOTCHA_SCRUB_KEEP_KEYS.
GOTCHA_SCRUB_KEEP_KEYSпустоТочные имена-исключения из денилиста (через запятую). Матч намеренно fail-closed: имя маскируется, если содержит слово из денилиста, поэтому author (содержит auth) и tokenizer (содержит token) по умолчанию маскируются. Недо-маскирование — это утечка ПДн, а избыточное стоит лишь потерянного отладочного поля, и эта настройка его возвращает: GOTCHA_SCRUB_KEEP_KEYS=author,tokenizer.
GOTCHA_SCRUB_FREETEXTfalseДополнительно маскирует email-адреса, встреченные в свободном тексте (сообщение об ошибке, значение исключения, описание спана). Выключено по умолчанию сознательно: наивная маскировка может испортить SQL-запросы или URL в тексте ошибки. Маскируются только email, не телефоны и не другие виды ПДн.

Ограничители и оценщики

Потолки, защищающие инстанс от лавины, и период фоновых оценщиков. Ограничивают РАБОТУ, а не хранение — поэтому вынесены из «Хранения» и «Квот», где стояли раньше.

ПеременнаяПо умолчаниюОписание
GOTCHA_NOTIFY_CONCURRENCY4Сколько уведомлений доставляется одновременно. Один медленный канал (мёртвый вебхук ждёт до 30 секунд) не задерживает остальные.
GOTCHA_ALERT_BUDGET_WINDOW_SECONDS3600Окно пер-проектного потолка уведомлений.
GOTCHA_ALERT_BUDGET_LIMIT50Сколько уведомлений проект может отправить за это окно. Троттлинг правил ключуется парой (issue, правило), а у нового issue строки троттлинга нет — поэтому отправитель с уникальным fingerprint на каждое событие получал уведомление на каждое событие. Подавленное не теряется: после закрытия окна уходит сводка «подавлено ещё N». 0 выключает потолок целиком.
GOTCHA_CARDINALITY_LIMIT10000Потолок РАЗЛИЧНЫХ значений открытых полей (имя транзакции, окружение, имя метрики, сервис, операция спана) на проект за окно. Значения сверх потолка не отбрасываются, а группируются под <cardinality-limit>; на затронутой странице показывается, по какому полю сработал потолок, и примеры сгруппированных значений. Причина почти всегда — идентификатор, попавший в имя, см. Кардинальность. 0 снимает ограничение.
GOTCHA_CARDINALITY_WINDOW_SECONDS3600Окно, после которого набор различённых значений начинается заново — проект, починивший имена, возвращается к нормальной работе сам.
GOTCHA_EVALUATORS_ENABLEDпо режимуЗапускать ли периодические циклы: регрессии производительности, правила по метрикам, регрессии профилей, встроенные пороги хостов (диск/память/нагрузка/тишина), SLO burn-rate (slo.Evaluator) и планировщик эскалаций (escalation.Scheduler) — всего шесть. По умолчанию они идут с режимами uptime и all, хотя к аптайму отношения не имеют. При раздельном развёртывании web+ingest (аптайм не используется) правило по метрике, SLO-алерт и эскалация выглядят включёнными и не вычисляются никогда — включите переменную ровно на одной реплике. При старте в режиме без оценщиков в лог пишется предупреждение.
GOTCHA_METRIC_EVAL_INTERVAL_SECONDS60Как часто (в секундах) проверяются пороговые правила алертов по метрикам.
GOTCHA_PROFILE_EVAL_INTERVAL_SECONDS300Как часто (в секундах) запускается детектор регрессий профилирования.
GOTCHA_HOST_EVAL_INTERVAL_SECONDS60Как часто (в секундах) фоновый оценщик пересчитывает встроенные пороги хостов (диск/память/нагрузка/тишина) и открывает/закрывает их инциденты, см. Хосты. Минимум — 1 секунда. Понижать имеет смысл только на маленьком парке: каждый тик — это запрос за последними точками по всем хостам проекта.
GOTCHA_SLO_EVAL_INTERVAL_SECONDS120Как часто (в секундах) фоновый оценщик пересчитывает burn rate по SLO на быстром/медленном окнах и открывает/закрывает инциденты сжигания бюджета. Минимум — 1 секунда. SLO живут на окнах в дни, поэтому такт медленнее, чем у оценщиков метрик/хостов, достаточен.
GOTCHA_ESCALATION_INTERVAL_SECONDS60Как часто (в секундах) планировщик эскалаций проверяет открытые неподтверждённые инциденты и продвигает лесенку на очередную ступень. Минимум — 1 секунда. Гейтится тем же GOTCHA_EVALUATORS_ENABLED, что и пять циклов выше.
GOTCHA_DEPENDENCY_SETTLE_SECONDS300Грейс схлопывания гонки при падении родителя в графе подавления шторма: сколько ждать, прежде чем отправить уведомление или эскалировать зависимый узел, у которого задекларирован родитель.

Наблюдаемость и логи

Детализация и формат логов самого инстанса.

ПеременнаяПо умолчаниюОписание
GOTCHA_LOGGING_LEVELinfoДетализация логов: debug, info, warn (алиас warning) или error, без учёта регистра. Поднимите до debug, чтобы получить больше подробностей во время инцидента, не пересобирая образ. Нераспознанное значение — отказ старта, а не тихий откат к info: опечатку в конфигурации логов (например, trace) нужно заметить сразу, а не искать в момент, когда детализации не хватает в разгар инцидента.
GOTCHA_LOGGING_FORMATtextФормат логов: text или json, без учёта регистра. json удобнее, когда логи уезжают в Loki/ELK. Нераспознанное значение — отказ старта.

Security (безопасность)

ПеременнаяПо умолчаниюОписание
GOTCHA_SECRET_KEYinsecure-dev-secretКлюч подписи сессионных и OAuth state-cookie, а также мастер-ключ шифрования at-rest (SSO client secret, токены каналов, заголовки мониторов). Дефолт публичен (он в исходном коде) — оставлять его на реальном сервере значит разрешить угон аккаунта через OAuth. На не-localhost GOTCHA_BASE_URL приложение отказывается стартовать в режимах web, all, ingest и uptime (везде, кроме probe), пока не задан свой ключ, и требует, чтобы он был не короче 32 байт (слишком короткий ключ — слабая подпись). Сгенерировать: openssl rand -hex 32. Для нестандартного dev-окружения обе проверки снимает GOTCHA_SECRET_KEY_ALLOW_INSECURE=1. Значение обрезается по краям — "ключ " и "ключ" дают один и тот же итоговый ключ, случайный пробел при копировании не меняет шифрование; строка из одних пробелов — отказ старта, а не тихий откат на публичный дефолт. Подробности — в Установке, шаг 5. Менять ключ на работающем инстансе — только по процедуре ротации, см. «Приватность и 152-ФЗ».
GOTCHA_SECRET_KEY_PREV(пусто)Предыдущий мастер-ключ на время ротации GOTCHA_SECRET_KEY — задаётся вместе с новым GOTCHA_SECRET_KEY на время перехода, затем убирается. Пока задан, приложение расшифровывает и им, и текущим ключом, а шифрует только текущим. В отличие от GOTCHA_SECRET_KEY, значение читается дословно, без обрезки пробелов по краям — чтобы ротация работала и для ключа, который хранился с хвостовым пробелом (тримминг превратил бы его в другой ключ и заблокировал бы расшифровку). Отсутствие тримминга не означает вседозволенность: значение из одних пробелов — та же ошибка гигиены, что и у GOTCHA_SECRET_KEY/GOTCHA_PG_DSN/GOTCHA_CH_DSN (скорее всего, случайный пробел при копировании, а не осознанный «ключ из пробелов»), и отказывает старт независимо от режима, а не тихо становится «настоящим» prev-ключом. Приложение отказывается стартовать при бессмысленной паре ключей: GOTCHA_SECRET_KEY_PREV равен текущему GOTCHA_SECRET_KEY, любой из них равен дефолтному dev-ключу при заданном GOTCHA_SECRET_KEY_PREV. GOTCHA_SECRET_KEY_ALLOW_INSECURE=1 эти проверки не снимает — это не про стойкость ключа, а про конфиг, который физически не может сделать то, что от него ждут. Процедура ротации — в «Приватность и 152-ФЗ».
GOTCHA_TRUSTED_PROXIES(пусто)Список через запятую: CIDR (10.0.0.0/8) и/или голые IP (192.168.1.5, трактуется как /32 или /128) доверенных обратных прокси. За прокси (рекомендуемая топология установки) укажите здесь адрес прокси — тогда пер-IP лимитер логина ключуется по реальному IP клиента из X-Forwarded-For, а не по адресу прокси; иначе все попытки входа выглядят пришедшими с прокси и лимитер не различает клиентов. Невалидные записи — ошибка старта, а не тихий пропуск.
GOTCHA_SECRET_KEY_ALLOW_INSECUREfalseАварийный обход проверки выше — позволяет стартовать с дефолтным ключом даже на не-localhost адресе. Только для нестандартных dev-стендов, никогда не используйте в реальной эксплуатации. Значение разбирается на каждом старте безусловно, независимо от того, достаточно ли стойкий GOTCHA_SECRET_KEY: нераспознанное значение (не 1/0/true/false/yes/no/on/off) — отказ старта, а не тихий пропуск опечатки.
GOTCHA_REGISTRATION_MODEinviteРежим самостоятельной регистрации (без учёта регистра значения): open — открыта всем; invite — аккаунт заводится только по действующему приглашению (по паролю или через провайдера); closedновых аккаунтов не появляется вообще, даже по действующему приглашению. В этом и разница: при closed приглашённый упрётся в «регистрация закрыта», и пригласить кого-то извне станет нельзя — приглашения работают только для тех, у кого аккаунт уже есть. Первый пользователь на чистом инстансе регистрируется всегда, независимо от настройки (bootstrap инстанс-админа).
GOTCHA_HSTS_ENABLEDtrueОтправляет ли само приложение Strict-Transport-Security — и только на ответах, отданных по https:// GOTCHA_BASE_URL (см. Усиление установки); на голом HTTP-деплое заголовок не уходит независимо от этой настройки. Настраивайте HSTS РОВНО в одном месте — либо на обратном прокси, либо в приложении, никогда в обоих сразу. Выключение НЕ снимает пин у браузеров: тот, что уже получил max-age=31536000, год будет отказываться от голого HTTP независимо от этой настройки — приложение лишь перестаёт отправлять заголовок, до кэша браузера ему не дотянуться. Единственный способ реально снять пин — реально отправленный max-age=0 (см. GOTCHA_HSTS_MAX_AGE_SECONDS ниже), для чего эта настройка обязана оставаться true.
GOTCHA_HSTS_MAX_AGE_SECONDS31536000Сколько секунд браузеру велено помнить требование HTTPS; дефолт — год. 0 — законное, осознанное значение, а не «выключено»: это единственный способ реально отозвать ранее отправленный пин — отправить GOTCHA_HSTS_ENABLED=true с этим значением 0, чтобы снять пин у браузеров, уже закэшировавших заголовок, а затем поднять значение обратно, когда авария позади. Если ещё выставлен GOTCHA_HSTS_PRELOAD=true, сначала выключите его (GOTCHA_HSTS_PRELOAD=false) — проверка preload ниже требует max-age не меньше года, поэтому 0 вместе с PRELOAD=true — отказ старта; полный порядок аварийного отката — в Усилении установки. Отрицательное значение — всегда опечатка, приложение отказывается стартовать.
GOTCHA_HSTS_INCLUDE_SUBDOMAINSfalseРасширяет требование HTTPS на все поддомены хоста из GOTCHA_BASE_URL, а не только на сам хост. По умолчанию выключено намеренно: инстанс Gotcha часто живёт на поддомене более крупного домена (например, gotcha.example.com), и включение заставило бы требовать HTTPS от КАЖДОГО другого сервиса на example.com — сервисов, на которые этот инстанс никак не влияет и которые могут быть даже не готовы к HTTPS. Включайте только если контролируете (или проверили HTTPS на) весь родительский домен целиком.
GOTCHA_HSTS_PRELOADfalseПомечает инстанс кандидатом на списки предзагрузки HSTS браузеров (зашиты прямо в браузер, минуя даже первый небезопасный запрос) — сама подача заявки описана в Усилении установки, эта переменная её не выполняет. Билет в один конец: как только домен зашит в релиз браузера, снять его оттуда можно месяцами, и это касается пользователей, которые вообще никогда не заходили на инстанс. Требует GOTCHA_HSTS_INCLUDE_SUBDOMAINS=true и GOTCHA_HSTS_MAX_AGE_SECONDS не меньше года — иначе приложение отказывается стартовать, потому что список предзагрузки всё равно отклонит заголовок без любого из двух условий, а оператор будет считать, что заявка уже подана.
GOTCHA_LOCALEruЯзык исходящих уведомлений (аптайм, регрессии, производительность) в email/Telegram/webhook: ru или en, без учёта регистра. У получателя вне веб-интерфейса нет своей локали, поэтому язык выбирает оператор — один на инстанс. Веб-интерфейс настройка не трогает: там каждый выбирает язык сам.
GOTCHA_SSRF_ALLOW_PRIVATEfalseРазрешить аптайм-проверкам и исходящим webhook-алертам обращаться к приватным/loopback/link-local адресам (например, 192.168.x.x, 127.0.0.1, 169.254.x.x). Держите false на любом инстансе, доступном нескольким пользователям/организациям — иначе один пользователь может завести «аптайм-проверку» или вебхук, который на самом деле сканирует вашу внутреннюю сеть (SSRF).
GOTCHA_SSRF_ALLOW_PRIVATE_UPTIMEнаследует GOTCHA_SSRF_ALLOW_PRIVATEРазрешить аптайм-проверкам ходить на приватные/loopback-адреса. Обычно единственный, который нужен: мониторить внутренний сервис — рутина, а цель задаёт админ организации.
GOTCHA_SSRF_ALLOW_PRIVATE_WEBHOOKнаследует GOTCHA_SSRF_ALLOW_PRIVATEРазрешить вебхукам алертов ходить на приватные адреса. Рискованнее: до 1 КБ ответа цели показывается на странице доставок, что превращает вебхук в читалку внутренних сервисов.
GOTCHA_SSRF_ALLOW_PRIVATE_OIDCнаследует GOTCHA_SSRF_ALLOW_PRIVATEРазрешить запросам OIDC (discovery/token) ходить на приватные адреса — нужно для внутреннего IdP. Рискованнее всего: client secret уходит на token_endpoint, взятый из discovery-документа.
GOTCHA_SSRF_ALLOW_PRIVATE_TELEGRAMнаследует GOTCHA_SSRF_ALLOW_PRIVATEРазрешить запросам к Telegram Bot API ходить на приватные адреса — нужно только когда GOTCHA_TELEGRAM_API_BASE указывает на внутренний прокси/бридж Telegram. Наименее опасный из четырёх: базовый URL задаёт оператор инстанса, а не арендатор, поэтому его нельзя превратить в пользовательский SSRF, как цель аптайма или вебхука.
GOTCHA_AUTO_MIGRATE_ENABLEDtrueПрименять миграции схемы БД автоматически при старте. false — миграции нужно применить отдельным шагом заранее, иначе приложение откажется стартовать на устаревшей схеме. Подробности и когда это нужно — в Обновлении.
GOTCHA_EXTERNAL_CHANNEL_DETAILS_ENABLEDfalseОтправлять ли текст ошибки (заголовок/culprit/тело) во внешние каналы алертов (Telegram/webhook). false — отправляется только обезличенная ссылка обратно на инстанс, без текста ошибки (текст ошибки может содержать персональные данные, которые вы не хотите, чтобы покидали периметр).
GOTCHA_TRUSTED_RECIPIENTSпустоДомены и хосты вашего контура через запятую: почта на этих доменах и вебхуки на этих хостах получают детали события даже при выключенном GOTCHA_EXTERNAL_CHANNEL_DETAILS_ENABLED. Совпадение по границе доменной метки (corp.example покрывает mail.corp.example, но не evilcorp.example). Хост инстанса из GOTCHA_BASE_URL и адреса внутренней сети доверенные всегда и без настройки. См. Приватность и 152-ФЗ.

Флаг командной строки --migrate-only применяет схему и завершает процесс, не поднимая ни одного компонента: init-job для развёртываний с GOTCHA_AUTO_MIGRATE_ENABLED=false. См. Обновление.

Режимы процесса: что запускает каждый --mode=

Роль процесса задаётся флагом бинаря --mode= (не переменной окружения): all по умолчанию — так работает штатный docker-compose.yml; web, ingest и uptime — для раздельного развёртывания на несколько реплик; probe — выносная проба (см. ниже). Таблица показывает, какие компоненты поднимает каждый режим. Все четыре режима с базой держат HTTP-слушатель со служебными ручками (/healthz, /readyz, /version, /metrics, см. Мониторинг самого gotcha) и на старте выполняют бэкфилл секретов под текущий GOTCHA_SECRET_KEY.

Компонентwebingestuptimeall
HTTP-приём телеметрии (/api/v1/*), писатели ClickHouse (события, спаны, метрики, профили, логи), детектор всплесков, учёт сигналов приёма
Интерфейс (все страницы, вход, SSO, API проб), джанитор сессий и просроченных приглашений
Воркер и джанитор выгрузок (если каталог GOTCHA_EXPORT_DIR доступен на запись)
Планировщик аптайма (ставит проверки в очередь)✓ (с предупреждением в логе: проверки ставятся, но не выполняются)
Исполнитель аптайм-проверок и watchdog (heartbeat, напоминания)
Доставка уведомлений: воркер outbox, дайджест подавленных, джанитор outbox
Оценщики: регрессии производительности, правила по метрикам, регрессии профилей, пороги хостов, SLO burn rate; планировщик эскалаций; джаниторы инцидентов и групп инцидентовтолько с GOTCHA_EVALUATORS_ENABLED=trueтолько с GOTCHA_EVALUATORS_ENABLED=true
Джанитор сущностей PostgreSQL по срокам хранения (проблемы, инциденты, регрессии, хосты, маркеры деплоя)
Очистка ClickHouse от телеметрии удалённых проектов

Отсюда два следствия для раздельного развёртывания. Во-первых, web — не «только интерфейс»: он доставляет уведомления и подчищает базу наравне с остальными, поэтому запись notify outbox janitor в его логе — норма, а не признак перепутанного режима. Во-вторых, без реплики uptime или all оценщики не работают нигде — поднимите их явно через GOTCHA_EVALUATORS_ENABLED=true ровно на одной реплике (см. «Ограничители и оценщики»).

Uptime & probe (аптайм и выносные пробы)

ПеременнаяПо умолчаниюОписание
GOTCHA_UPTIME_CONCURRENCY50Сколько аптайм-проверок выполняется одновременно (в режимах uptime/all, а также выносной пробой в режиме probe).
GOTCHA_UPTIME_LOCAL_REGIONlocalИмя встроенного локального региона аптайм-проверок — то, что видно в интерфейсе при выборе региона монитора.
GOTCHA_PROBE_KEY(пусто)Только для --mode=probe: bearer-токен, которым выносная проба аутентифицируется к центральному инстансу. Обязателен в этом режиме.
GOTCHA_PROBE_SERVER_URL(пусто)Только для --mode=probe: базовый URL центрального инстанса Gotcha, к которому подключается проба. Обязателен в этом режиме, должен быть абсолютным http(s)-адресом без запроса и фрагмента; хвостовая косая срезается сама. Задан в другом режиме — переменную никто не читает, в лог пишется предупреждение, старт продолжается.

Режим --mode=probe — это отдельный процесс, разворачиваемый в другом регионе/дата-центре: он не открывает ни PostgreSQL, ни ClickHouse, только ходит наружу к центральному инстансу по HTTP.

Agent distribution (раздача бинарей агента)

ПеременнаяПо умолчаниюОписание
GOTCHA_DIST_DIR/opt/gotcha/agent-distКаталог с install.sh и собранными бинарями gotcha-agent (gotcha-agent-linux-amd64, gotcha-agent-linux-arm64, SHA256SUMS), которые инстанс раздаёт по GET /install.sh и GET /agent/{file} — именно с этого пути тянет команда установки агента (см. Хосты). Дефолт совпадает с путём, куда Docker-сборка кладёт бинари в образ, — на штатном docker-compose-проде задавать переменную не нужно. Каталога по этому пути физически нет в dev-режиме (go run без Docker) или на сборке не из Docker-образа — тогда оба маршрута отвечают 404 с подсказкой, а не падают. Значение задаёт только каталог раздачи: сам скрипт install.sh встроен в бинарь gotcha и одинаков для всех инстансов и версий продукта.
GOTCHA_DIST_RATE_PER_MIN120Порог per-IP лимитера GET /agent/{file} (загрузка бинаря агента и SHA256SUMS). Одна установка/обновление стоит 2 запроса, поэтому дефолт даёт ~60 хостов в минуту с одного IP — с запасом для массовой раскатки (Ansible/Terraform) или обновления парка за одним NAT/egress-адресом. Поднимите значение, если за одним IP стоит парк больше. 0 (и отрицательное значение) снимает лимит полностью — GET /agent/{file} перестаёт резаться по частоте, как и у *_RETENTION_DAYS, где 0 означает «без границы».

Выгрузки (export)

Подробности фичи и ограничений — в Выгрузках.

ПеременнаяПо умолчаниюОписание
GOTCHA_EXPORT_DIR/var/lib/gotcha/exportsКаталог на диске инстанса, куда воркер пишет файлы выгрузок. В штатном docker-compose.yml это именованный том exportdata, переживающий пересоздание контейнера. Если каталог не удаётся создать на старте (нет прав, занято не-каталогом) или он существует, но недоступен на запись этому процессу (например, точку монтирования свежего тома создал сам Docker и она досталась не тому владельцу) — приложение не падает: раздел выгрузок молча выключается — сама страница /projects/{id}/exports при этом по-прежнему отвечает 200 с пояснением, что раздел недоступен на этом инстансе, а не пустой таблицей; 404 получают только постановка/скачивание/удаление заявки (см. Выгрузки). В лог пишется предупреждение. Каталог создаётся с правами 0700 (в нём лежат ПДн из событий/ошибок, как и в файлах внутри — они уже 0600): создание не меняет режим уже существующего каталога, поэтому на инсталляциях, где каталог достался с более широкими правами (например 0755 от Docker при монтировании тома, см. выше), права нужно поправить вручную — chmod 0700.
GOTCHA_EXPORT_RETENTION_HOURS168Через сколько часов после завершения заявки готовый файл удаляется фоновым джанитором (заявка помечается «истекла»). 168 — семь суток. Строка заявки в истории живёт дольше: не меньше 30 суток от завершения, подробнее в Выгрузках. В отличие от GOTCHA_DIST_RATE_PER_MIN выше, 0 и отрицательное значение здесь НЕ означают «без ограничения» — файл считался бы истёкшим сразу после сборки. Приложение отказывается стартовать с таким значением.
GOTCHA_EXPORT_MAX_ROWS200000Потолок строк одной выгрузки: при достижении заявка помечается «обрезана» (Truncated), сборка останавливается детерминированно, а не молча отдаёт неполный файл без пометки. 0 и отрицательное значение здесь НЕ означают «без лимита» (не та же конвенция, что у GOTCHA_DIST_RATE_PER_MIN/*_RETENTION_DAYS) — приложение отказывается стартовать.
GOTCHA_EXPORT_MAX_BYTES268435456Потолок размера файла одной выгрузки в байтах (256 МиБ). Тот же смысл, что у GOTCHA_EXPORT_MAX_ROWS, но по объёму, а не по числу строк; та же оговорка про 0 и отрицательные значения.
GOTCHA_EXPORT_DISK_BUDGET_BYTES5368709120Суммарный бюджет каталога GOTCHA_EXPORT_DIR в байтах (5 ГиБ). Проверяется до начала записи файла, а не частично записанный файл. Переполнение — ВРЕМЕННЫЙ отказ новой заявки (до 3 попыток, см. Выгрузки) — самоустраняется первым же проходом джанитора, который освобождает диск от истёкших файлов. 0 и отрицательное значение здесь НЕ означают «без бюджета» — «занято ≥ бюджет» истинно уже на пустом каталоге, и КАЖДАЯ заявка отказывала бы без единой попытки; приложение отказывается стартовать с таким значением.

OAuth / SSO

Каждый провайдер входа включается независимо. Если включить провайдер, не задав его обязательные секреты — приложение откажется стартовать.

ПеременнаяПо умолчаниюОписание
GOTCHA_OIDC_ENABLEDfalseВключает вход через произвольный OIDC-провайдер (Keycloak, Authentik, Google Workspace и т.п.). Требует GOTCHA_OIDC_ISSUER, GOTCHA_OIDC_CLIENT_ID, GOTCHA_OIDC_CLIENT_SECRET.
GOTCHA_OIDC_ISSUER(пусто)URL издателя (issuer) OIDC-провайдера.
GOTCHA_OIDC_CLIENT_ID(пусто)Идентификатор приложения, зарегистрированного у провайдера.
GOTCHA_OIDC_CLIENT_SECRET(пусто)Секрет того же приложения.
GOTCHA_OIDC_SCOPESopenid email profileПолный список scope через запятую (тот же разделитель, что у остальных списочных переменных этого документа), который уходит провайдеру — перед отправкой запятая нормализуется в пробел, как того требует сам протокол. Заданное значение заменяет список по умолчанию, а не дополняет его, поэтому всегда включайте openid и email: без них в ID-токене не будет ни субъекта, ни адреса, и вход перестанет работать. Чтобы запросить дополнительный scope, перечислите его вместе со стандартными: openid,email,profile,groups. Пустые элементы (лишняя запятая) отбрасываются; значение из одних запятых и пробелов трактуется как незаданное — уходит дефолт.
GOTCHA_OIDC_DISPLAY_NAME(пусто)Отображаемое имя кнопки входа («Войти через …») в интерфейсе.
GOTCHA_YANDEX_ENABLEDfalseВключает вход через Yandex ID. Требует GOTCHA_YANDEX_CLIENT_ID/GOTCHA_YANDEX_CLIENT_SECRET.
GOTCHA_YANDEX_CLIENT_ID(пусто)Идентификатор приложения, зарегистрированного в Yandex ID.
GOTCHA_YANDEX_CLIENT_SECRET(пусто)Секрет того же приложения.
GOTCHA_VK_ENABLEDfalseВключает вход через VK ID. Требует GOTCHA_VK_CLIENT_ID/GOTCHA_VK_CLIENT_SECRET.
GOTCHA_VK_CLIENT_ID(пусто)Идентификатор приложения, зарегистрированного в VK ID.
GOTCHA_VK_CLIENT_SECRET(пусто)Секрет того же приложения.

Пошаговая настройка каждого провайдера — в SSO.

Что дальше