Установка

Эта инструкция рассчитана на то, что вы никогда раньше не разворачивали Docker-приложения и не администрировали Linux-сервер. Все команды даны в готовом для копирования виде.

Что понадобится

  • Linux-сервер (VPS/выделенный сервер) — подойдёт Ubuntu 22.04/24.04, Debian 12 или дистрибутив RedHat-семейства (AlmaLinux 9/10, Rocky Linux 9/10, RHEL 9/10). Требования к CPU/RAM/диску — в таблице ниже.
  • Docker и Docker Compose — единственная зависимость. Больше ничего (ни PHP, ни nginx, ни базы данных) устанавливать вручную не нужно — всё это уже упаковано в контейнеры.
  • Доступ к серверу по SSH.
  • (Не обязательно, но желательно для реальной эксплуатации) доменное имя, указывающее на IP сервера.

Системные требования

Gotcha поднимает на одном сервере три процесса: само приложение (Go), PostgreSQL и ClickHouse. Основной потребитель памяти и диска — ClickHouse, в котором хранится телеметрия (события, трейсы, метрики, профили), поэтому и требования определяются в первую очередь им.

МинимумРекомендуется
CPU2 vCPU4 vCPU
RAM2 ГБ4 ГБ и больше
Диск20 ГБ SSD40 ГБ SSD и больше
  • ОС: Ubuntu 22.04/24.04, Debian 12 или RedHat-семейство (AlmaLinux 9/10, Rocky Linux 9/10, RHEL 9/10), архитектура x86-64 (amd64). Gotcha работает в Docker, поэтому дистрибутив почти не важен — различия только в командах установки Docker/git и в файрволе, они отмечены по ходу инструкции.
  • RAM. 2 ГБ — рабочий минимум для запуска и небольшой нагрузки (личные проекты, стейджинг). Для продакшена с реальным потоком событий закладывайте от 4 ГБ: под нагрузкой ClickHouse тем стабильнее, чем больше ему доступно памяти.
  • Диск. Растёт вместе с объёмом телеметрии и сроком её хранения (retention). 20 ГБ хватает, чтобы стартовать; при заметном трафике или длинном retention планируйте больше и следите за свободным местом — как именно, см. Мониторинг gotcha. Диск обязательно SSD — и ClickHouse, и PostgreSQL чувствительны к его латентности.
  • CPU. Двух ядер достаточно; дополнительные ядра ускоряют приём всплесков событий и запросы ClickHouse.
  • Сеть. Наружу нужен только один порт приложения (по умолчанию 59080). PostgreSQL и ClickHouse наружу не выставляются — они доступны лишь внутри docker-сети.

Если сервер на минимуме (2 vCPU / 2 ГБ)

Заводские настройки PostgreSQL и ClickHouse рассчитаны на крупные серверы. На минимальной конфигурации они заметно тратят ресурсы впустую: ClickHouse по умолчанию ведёт подробные системные логи без ограничения срока хранения, и на слабой машине их обслуживание съедает больше, чем полезная работа.

Для таких серверов есть готовый оверлей — запускайте с двумя файлами:

docker compose -f docker-compose.yml -f docker-compose.small.yml up -d

Замеры на VPS 2 ядра / 2 ГБ / 20 ГБ SSD: память ClickHouse снизилась с 880 до 295 МБ, занятое место на диске — с 12 до 9.2 ГБ, load average — с 1.15 до 0.79.

Оверлей ставит потолки, осмысленные только на слабом железе. На сервере с запасом ресурсов его применять не нужно — там он ограничит приём событий и замедлит запросы. Обычный запуск (docker compose up -d) уже включает настройки, полезные на любой машине.

Шаг 1. Проверьте, установлен ли Docker

Подключитесь к серверу по SSH и выполните:

docker --version
docker compose version

Если обе команды напечатали номер версии — Docker уже есть, переходите к шагу 2.

Если вы видите command not found, ставьте Docker. Команды зависят от того, какое у сервера семейство дистрибутивов, — выберите свой раздел.

Ubuntu, Debian и другие deb-дистрибутивы

Официальный скрипт Docker делает всё сам:

curl -fsSL https://get.docker.com | sudo sh

Docker Compose (команда docker compose, с пробелом) ставится вместе с Docker, отдельно не нужен. Сервис после установки запускается сам.

AlmaLinux, Rocky Linux, RHEL и другие rpm-дистрибутивы

Здесь есть две ловушки, из-за которых установка «по привычке» заканчивается неработающим сервером.

Ловушка первая: dnf install docker ставит не Docker. В штатных репозиториях RedHat-семейства пакета Docker нет, а есть podman-docker — обёртка, которая эмулирует команду docker поверх Podman. Выглядит это так:

# dnf install docker
...
Installed: podman-docker-5.8.2-5.el9_8.noarch

# docker --version
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
podman version 5.8.2

# sudo usermod -aG docker $USER
usermod: group 'docker' does not exist

# sudo systemctl enable --now docker
Failed to enable unit: Unit file docker.service does not exist.

Группы docker нет, сервиса docker нет — потому что и Docker никакого нет.

Ловушка вторая: официальный скрипт установки не поддерживает AlmaLinux. curl -fsSL https://get.docker.com | sudo sh на ней отвечает ERROR: Unsupported distribution 'almalinux'.

Правильный путь — официальный репозиторий Docker CE. Если ранее ставили podman-docker, его придётся удалить: он занимает то же имя команды /usr/bin/docker, и установка Docker CE поверх него падает с конфликтом пакетов.

# 1. Убрать обёртку Podman, если она была установлена
sudo dnf remove -y podman-docker

# 2. Подключить официальный репозиторий Docker
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 3. Установить Docker и плагин Compose
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 4. Запустить сервис и включить автозапуск (сам он не стартует)
sudo systemctl enable --now docker

Репозиторий именно centos — Docker не собирает отдельные пакеты для AlmaLinux и Rocky, а собранные для CentOS Stream на них работают. Проверено на AlmaLinux 9 и 10.

После установки (любой дистрибутив)

Добавьте своего пользователя в группу docker, чтобы не набирать sudo перед каждой командой, и перезайдите по SSH, чтобы это применилось:

sudo usermod -aG docker $USER
exit

Зайдите на сервер заново и повторите docker --version и docker compose version — обе команды должны напечатать номер версии.

Шаг 2. Скачайте код Gotcha

Если на сервере есть git

# gitflic (основной, анонимный HTTPS)
git clone https://gitflic.ru/project/otezvikentiy/gotcha.git
# GitHub (зеркало)
git clone https://github.com/OtezVikentiy/gotcha.git
# Контрибьюторы с SSH-доступом могут использовать:
# git clone git@gitflic.ru:otezvikentiy/gotcha.git
cd gotcha

Если git не установлен

Ставить его необязательно — можно скачать архив с зеркала на GitHub и распаковать. curl и tar есть в любом дистрибутиве из коробки:

curl -fsSL https://github.com/OtezVikentiy/gotcha/archive/refs/heads/main.tar.gz -o gotcha.tar.gz
tar xzf gotcha.tar.gz
cd gotcha-main

Разница с git clone только одна: обновляться потом придётся тем же способом — скачивать свежий архив, а не делать git pull. Если планируете обновлять инстанс регулярно, git всё же удобнее: sudo apt install -y git для Ubuntu/Debian, sudo dnf install -y git для AlmaLinux/Rocky/RHEL.

В распакованной папке лежит docker-compose.yml — файл-рецепт, который описывает, какие три контейнера нужно поднять и как их связать между собой. Все дальнейшие команды выполняются из неё.

Шаг 3. Запустите контейнеры

make up-rebuild

(make вычисляет git-версию и вшивает её в сборку — /version и страница «О программе» назовут точный релиз. Если make не установлен, сработает и docker compose up -d, но инстанс будет представляться как «no build metadata» вместо проверяемой версии.)

Что произойдёт:

  1. Docker соберёт образ приложения Gotcha (компилирует Go-программу в контейнере — при первом запуске это может занять пару минут).
  2. Поднимутся три контейнера:
    • gotcha — само приложение: HTTP-сервер, веб-интерфейс, приём событий от SDK, миграции схемы БД при старте.
    • postgres (PostgreSQL 17) — хранит «обычные» данные: пользователей, организации, проекты, правила алертов, инциденты.
    • clickhouse (ClickHouse 25.3) — хранит большие объёмы телеметрии: сами события об ошибках, трейсы, метрики, профили, результаты аптайм-проверок.
  3. Флаг -d («detached») означает «запустить в фоне и вернуть терминал» — контейнеры продолжат работать после того, как вы закроете SSH-сессию.

Postgres и ClickHouse наружу (на хост-машину) не выставлены — до них можно достучаться только изнутри docker-сети, между контейнерами. Наружу торчит только порт приложения.

Проверьте статус:

docker compose ps

Все три строки должны показывать Uppostgres и clickhouseUp (healthy), у gotcha может уйти на подъём до минуты первый раз, пока применяются миграции).

Шаг 4. Проверьте, что всё поднялось

Приложение слушает порт 59080 на хосте по умолчанию (см. docker-compose.yml: "${GOTCHA_PORT:-59080}:8080" — это порт хоста слева, порт контейнера справа; выбран нестандартный 59080, чтобы не конфликтовать с другими сервисами на сервере). Проверьте health-эндпойнт:

curl -sf http://localhost:59080/readyz

Ответ вида {"status":"ready","clickhouse":"ok","postgres":"ok"} с HTTP-кодом 200 означает, что приложение поднялось и обе базы данных ему отвечают. Если curl завис или вернул ошибку — см. раздел «Устранение неполадок» ниже.

Ручек две, и отвечают они на разные вопросы:

РучкаВопросКогда отдаёт 503
/healthzпроцесс жив?никогда, пока отвечает HTTP
/readyzготов работать?пока PostgreSQL или ClickHouse недоступны

Разница важна при настройке оркестратора: /healthz — для liveness-пробы (перезапустить зависший процесс), /readyz — для readiness (не слать трафик). Если повесить liveness на /readyz, сбой хранилища превратится в перезапуск живого контейнера, а каждый перезапуск выбрасывает то, что накопилось в буферах в ожидании возвращения хранилища.

Готовые обёртки есть в Makefile, если вы предпочитаете make:

make up       # docker compose up -d
make ps       # docker compose ps
make health   # curl /readyz
make logs     # docker compose logs -f gotcha (Ctrl+C для выхода)

Откройте в браузере http://<IP-адрес-вашего-сервера>:59080 (или http://localhost:59080, если открываете с самого сервера/через SSH-туннель) — должна открыться страница входа Gotcha.

Шаг 5. Задайте секретный ключ (обязательно для реального сервера)

Эти два шага настройки идут до создания первого пользователя намеренно: регистрация — это POST-запрос, и с неверным GOTCHA_BASE_URL тот самый первый POST будет отклонён с 403 (см. шаг 6).

По умолчанию Gotcha использует GOTCHA_SECRET_KEY=insecure-dev-secret. Значение публично — оно лежит прямо в исходном коде на GitFlic, его знает кто угодно. Этим ключом подписываются сессионные cookie и OAuth state-cookie; если оставить дефолт на сервере, доступном по интернету, злоумышленник, знающий этот ключ, может подделать cookie и увести чужой аккаунт через OAuth-вход (account takeover).

Поэтому: если ваш GOTCHA_BASE_URL не localhost/127.0.0.1 (то есть у вас настоящий сервер, а не локальная разработка), приложение откажется стартовать в режимах web, all, ingest и uptime (везде, кроме probe), пока вы не зададите свой ключ.

Сгенерируйте случайный ключ:

openssl rand -base64 32

Создайте файл .env рядом с docker-compose.yml — Docker Compose читает его автоматически. Той же командой ограничьте права на файл: в нём будет лежать мастер-ключ, которым шифруются секреты каналов алертов и SSO, а возможно и пароль SMTP (Резервное копирование уже требует 600 для копии этого файла — оригинал не должен быть слабее):

cp .env.example .env && chmod 600 .env
nano .env

Раскомментируйте GOTCHA_SECRET_KEY и замените значение на то, что вывела команда выше:

GOTCHA_SECRET_KEY=вставьте-сюда-случайную-строку-из-openssl

Примените изменение (пересоздаёт контейнер gotcha с новой переменной окружения):

docker compose up -d

Шаг 6. Укажите публичный адрес (GOTCHA_BASE_URL)

GOTCHA_BASE_URL — это адрес, по которому пользователи и SDK на самом деле обращаются к вашему инстансу. Из него строятся: DSN проектов (то, что вы вставляете в код приложений), ссылки в письмах-приглашениях, ссылки на инциденты в алертах (Telegram/webhook/email). Он же — эталон для проверки происхождения, защищающей каждую форму: POST с адреса, отличного от GOTCHA_BASE_URL, отклоняется с 403 — включая форму регистрации на следующем шаге.

Раскомментируйте в том же .env:

GOTCHA_BASE_URL=https://gotcha.example.com

(или http://<IP-сервера>:59080, если пока без домена и без HTTPS — но см. чек-лист ниже, почему HTTPS важен). Примените:

docker compose up -d

Шаг 7. Создайте первого пользователя

Откройте http://<адрес-сервера>:59080/register и зарегистрируйтесь.

Важно: первый пользователь на чистом инстансе регистрируется всегда, независимо от режима самостоятельной регистрации (GOTCHA_REGISTRATION), и автоматически получает права инстанс-администратора. Это «bootstrap» — так вы получаете первого админа на свежей установке без ручных манипуляций с базой. Все последующие регистрации уже подчиняются GOTCHA_REGISTRATION (подробнее — Конфигурация).

После входа: создайте организацию, затем проект внутри неё. На странице проекта «Подключение» (URL вида /projects/<id>/setup, также доступна кнопкой «Подключение SDK» в списке проектов) будет DSN — адрес, на который направляется SDK вашего приложения (Sentry SDK любого языка работает с Gotcha без изменений, так как используется тот же протокол приёма). Подробный разбор — Первые шаги и SDK и интеграции.

Минимальный чек-лист для продакшена

Прежде чем давать доступ реальным пользователям/направлять на инстанс реальный трафик приложений, убедитесь:

  • GOTCHA_SECRET_KEY — задан свой случайный ключ (шаг 5), не дефолтный.

  • GOTCHA_BASE_URL — указывает на реальный публичный адрес.

  • HTTPS — Gotcha сам TLS не терминирует, поставьте перед ним reverse-proxy:

    • nginx: конфиг с proxy_pass http://127.0.0.1:59080; и сертификатом от Let’s Encrypt (certbot --nginx).
    • Caddy: ещё проще, HTTPS настраивается автоматически — в Caddyfile достаточно строки gotcha.example.com { reverse_proxy localhost:59080 }.

    Без HTTPS сессионные cookie идут по сети открытым текстом — сервер даже предупредит об этом в логах (GOTCHA_BASE_URL is non-local plain HTTP).

  • SMTP — без него не работают письма-приглашения и email-канал алертов. Настройка — в Конфигурации.

  • Резервное копирование — настройте до того, как в базе появятся важные данные. См. Резервное копирование и восстановление.

  • Квоты — если DSN проекта может утечь публично (например, фронтенд-JS), задайте GOTCHA_DEFAULT_*_QUOTA (по умолчанию в oss-редакции — безлимит). См. Конфигурацию.

Устранение неполадок

Контейнеры не стартуют / падают. Посмотрите логи:

docker compose logs -f gotcha
docker compose logs -f postgres
docker compose logs -f clickhouse

Частая причина — сообщение об ошибке конфигурации (например, требование задать GOTCHA_SECRET_KEY, см. шаг 5) прямо в логе gotcha.

Порт уже занят (bind: address already in use). На сервере что-то уже слушает 59080. Задайте другой порт хоста через .env:

GOTCHA_PORT=8081

и docker compose up -d. Приложение внутри контейнера по-прежнему слушает 8080 — меняется только то, на какой порт хоста он «пробрасывается».

Не открывается веб-интерфейс, хотя контейнеры Up.

  • Проверьте firewall на сервере. Ubuntu/Debian: sudo ufw status — при включённом ufw разрешите порт: sudo ufw allow 59080/tcp. AlmaLinux/Rocky/RHEL: firewalld включён по умолчанию — разрешите порт: sudo firewall-cmd --permanent --add-port=59080/tcp && sudo firewall-cmd --reload.
  • Если сервер у облачного провайдера/хостинга — проверьте Security Group / файрвол в панели управления хостингом отдельно от ufw (часто трафик режется именно там).
  • Проверьте curl -sf http://localhost:59080/healthz с самого сервера — если это работает, а снаружи нет, проблема сетевая (firewall/провайдер), а не в Gotcha.

Формы, регистрация или логин отдают forbidden (403). Gotcha защищает POST-запросы проверкой источника: Origin/Referer запроса должен совпадать с GOTCHA_BASE_URL по scheme и host. Если открыть интерфейс по адресу, отличному от GOTCHA_BASE_URL (например, по http://localhost, когда BASE_URL — публичный HTTPS-домен, или через туннель/прокси с другим хостом), любой POST срежется в 403. Открывайте UI строго по адресу из GOTCHA_BASE_URL.

/readyz отвечает 503 со статусом unavailable у postgres/clickhouse. Значит приложение живо (/healthz отвечает 200), но не может достучаться до одной из баз. Обычно это означает, что база ещё не поднялась (первый запуск ClickHouse может занимать до минуты) — подождите и повторите. Если не проходит долго — смотрите docker compose logs postgres / docker compose logs clickhouse.

Что дальше