Как я установил Telepilot: 6 багов и решение за 1 день

Утром я рассчитывал закончить за два часа. Поставить Telepilot на сервер Азамата, подключить 5 чат-парсеров к 130 Telegram-чатам и к обеду уже переключиться на другие задачи. Вместо этого — 6 последовательных багов, которые разложили всю схему. К вечеру всё работало. Парсеры крутились, данные собирались, Азамат доволен. Но день ушёл целиком. Раньше такой объём установки занимал у команды из 4 человек примерно неделю — с тестами, итерациями и пересылкой логов по почте. Здесь я один, плюс агенты. Это первая установка Telepilot за пределами моей собственной инфраструктуры Solar Property.

Пишу этот разбор не потому что хочу похвастаться. А потому что 6 конкретных технических проблем — это готовый материал для следующего, кто будет разворачивать продукт у клиента. Каждый баг мог стоить ещё пару часов, если бы я не документировал по ходу. В итоге все 6 попали в roadmap Phase 5, и следующая установка будет в разы быстрее.

Что такое Telepilot и зачем он понадобился Азамату

Telepilot — система автоматического мониторинга Telegram-чатов. Разворачиваешь чат-парсеры на сервере, указываешь список групп и каналов, задаёшь фильтры — и система собирает всё, что там происходит, в реальном времени. Без ручного просмотра, без пропущенных сообщений, без найма людей, которые сидят и читают.

Азамат работает в нише, где важно оперативно отслеживать упоминания в тематических Telegram-сообществах. У него 130 чатов разной активности — от небольших групп на 200 человек до крупных каналов с десятками тысяч подписчиков. Вручную это физически невозможно. Ни один сотрудник не охватит такой объём в реальном времени. Чат-парсер — единственное рабочее решение.

До меня Азамат пробовал несколько готовых решений. Проблема стандартная: либо слишком дорого при таком масштабе, либо нет нужной гибкости в фильтрах, либо сервис лежит в самый неподходящий момент. Telepilot разворачивается на его собственном сервере — это значит полный контроль над данными, никакой зависимости от третьих лиц и фиксированные расходы без роста от количества чатов.

На бумаге план простой: сервер есть, SSH-доступ есть, инструкция у меня есть. Два часа — и работает. На практике сервер оказался на Debian, у меня вся разработка и тесты на Ubuntu. Это и стало корнем большей части проблем.

Почему именно мониторинг Telegram, а не другие платформы? Телеграм стал основным каналом профессиональных сообществ в русскоязычном сегменте. Там идут реальные обсуждения, там появляются лиды, там публикуются предложения раньше, чем попадают на маркетплейсы. Кто мониторит эти чаты в реальном времени — тот реагирует первым. 130 чатов — это объём, при котором ручной мониторинг даже силами 3-4 человек даёт запаздывание в несколько часов. Автоматический парсер закрывает это окно полностью: любое совпадение по фильтру — и уведомление приходит в течение секунд.

Первый запуск: когда план не переживает контакта с реальностью

Я зашёл по SSH, клонировал репозиторий, запустил install.sh. Скрипт отработал без ошибок. Хорошее начало. Запустил главный сервис — упал. Прочитал лог — непонятно, на первый взгляд, почему. Запустил повторно с дебаг-флагом — другая ошибка. Понял, что это не случайность.

Первая диагностика заняла минут двадцать. Не потому что медленно соображал, а потому что баг проявлялся косвенно — сервис стартовал, пару секунд жил, потом падал с generic-ошибкой соединения. В логах — ничего конкретного. Пришлось идти через stacktrace вручную.

К этому моменту я уже понял: дело не в одном баге. Скорее всего, цепочка. И если не документировать каждый по ходу — к концу дня забуду детали первых трёх. Открыл отдельный файл, назвал его deployment-bugs-azamat.md, и начал записывать. Это решение сэкономило несколько часов только на этой установке, и сколько-то — на следующих.

Важный момент про диагностику в незнакомом окружении: нельзя доверять первому сообщению об ошибке. Оно почти всегда — симптом, а не причина. Generic «connection refused» может означать пять разных вещей: сервис не стартовал, стартовал на другом порту, стартовал и упал, ждёт другой сервис, или просто неправильный хост в конфиге. Каждую гипотезу нужно проверять отдельно, с конкретными командами, а не угадывать по интуиции.

Ещё один урок из этого дня: не пытаться воспроизвести баг локально сразу же. Моё окружение — Ubuntu, у клиента Debian. Если я воспроизведу что-то у себя, это не значит, что там это то же самое. Диагностировать нужно прямо на сервере, где проявился баг, через SSH. Это медленнее, чем работать локально, но зато точно знаешь, что исправляешь реальную проблему, а не артефакт другого окружения.

6 багов разобранных по косточкам

Все 6 — реальные, в том порядке, в котором проявились.

Баг 1: install.sh перетирал конфиг при повторном запуске

Сценарий простой: запустил install.sh, он отработал. Я вручную подредактировал config.yaml под параметры сервера Азамата — имя базы, порт, ключи API. Потом запустил deploy.sh для старта сервисов, и он внутри снова вызвал часть install.sh. Та часть перезаписала config.yaml шаблоном из репозитория. Мои правки — пропали.

Это классическая ошибка идемпотентности скрипта. install.sh должен проверять, существует ли уже config.yaml с пользовательскими настройками, и не трогать его при повторном запуске. В моей Solar-версии такой проблемы не было — я никогда не запускал install.sh дважды на одном сервере. У клиента — запустил для проверки окружения, потом начал редактировать конфиг, потом deploy.sh дёрнул install.sh снова. Фикс: добавить в install.sh guard типа if [ -f config.yaml ]; then echo "config exists, skipping"; fi. Пока — вручную сохранять конфиг перед запуском деплоя.

Баг 2: Debian клал Python-пакеты по нестандартным путям

На Ubuntu pip3 install кладёт пакеты в /usr/local/lib/python3.X/dist-packages или в ~/.local/lib/. На Debian с определёнными флагами компиляции — в /usr/lib/python3/dist-packages. Разница небольшая, но скрипт запуска искал модули строго по Ubuntu-пути.

Симптом: ImportError при старте. Модуль установлен (pip show показывает версию), но Python его не видит. Прошёлся sys.path — нужная директория там не числилась. Добавил явный PYTHONPATH в systemd unit-файл для этого сервера. Рабочий обход, пока не перепишем install.sh с учётом дистрибутива и автоматическим определением пути.

Баг 3: кластер парсеров не стартовал из-за порядка запуска сервисов

Telepilot запускает несколько сервисов: основной оркестратор, worker'ы-парсеры и брокер очередей. Они зависят друг от друга, и порядок имеет значение. Systemd-юниты были написаны с After= директивами, но у Debian другие дефолтные таймауты ожидания готовности сервиса.

Оркестратор стартовал раньше, чем брокер успевал поднять очередь. Оркестратор пытался подключиться — получал отказ — падал. Брокер к этому моменту только-только поднялся. Systemd видел два упавших юнита, перезапускал оба одновременно, и цикл повторялся. В логах это выглядело как бесконечный restart loop с одинаковой ошибкой.

Обход: добавил в юнит оркестратора явный ExecStartPre=/bin/sleep 5 перед exec. Неэлегантно, но работает стабильно. В roadmap Phase 5 — переписать на health-check с Type=notify в брокере вместо sleep.

Баг 4: миграции БД искали переменную с одним именем, deploy.sh экспортировал с другим

В файле миграций Alembic ожидал переменную DATABASE_URL в стандартном формате. В deploy.sh была строка export DB_URL=postgresql://... — другое имя. На моём сервере в ~/.bashrc был установлен DATABASE_URL отдельно, поэтому миграции находили переменную и проходили. На чистом сервере Азамата — только то, что экспортирует deploy.sh. Alembic не находил DATABASE_URL и падал с EnvironmentError: DATABASE_URL is not set.

Фикс прямой: добавить в deploy.sh строку export DATABASE_URL=$DB_URL перед вызовом миграций. Две минуты работы. Но найти это заняло двадцать — потому что ошибка Alembic была невнятная при определённых версиях, и я сначала подозревал неправильный формат строки подключения или права доступа к базе.

Баг 5: systemd-юнит ссылался на Python-модуль, которого нет в установленном пакете

ExecStart в одном из юнитов выглядел как: python3 -m telepilot.workers.queue_processor. Этот модуль в репозитории существовал — файл на месте, импорты работают при запуске из директории репозитория. Но в pip-пакете его не было: он был включён только как часть source distribution, не как installed package. При pip install . он не попадал в site-packages.

На моей машине я запускал не через pip install ., а напрямую из директории с исходниками, поэтому Python видел все модули через текущую директорию. Чистая установка через pip на Debian — не видел. Решение в roadmap: добавить модуль явно в packages= в pyproject.toml. Временный обход — заменить в юните на python3 /opt/telepilot/workers/queue_processor.py с абсолютным путём.

Баг 6: пул соединений к PostgreSQL создавался в закрытом состоянии

Последний баг был самым неочевидным. Asyncpg connection pool инициализировался при старте сервиса, create_pool() возвращал объект без ошибок. Но первые запросы к базе падали с ошибкой «connection is closed». В логах — пул создан успешно. Соединения внутри уже закрыты.

Причина: я инициализировал пул в синхронном контексте запуска, а не в async функции. На Python 3.10 это работало из-за изменений в asyncio event loop policy. На Python 3.11 у Азамата — поведение event loop при создании пула из синхронного контекста изменилось. Пул создавался, но его внутренние соединения немедленно закрывались, потому что event loop, в котором они открылись, уже не был активным к моменту первого запроса.

Фикс: перенести инициализацию пула в async lifespan-функцию FastAPI, которую await'ит фреймворк при старте. Изменение в 3 строки кода, диагностика через asyncio debug mode и добавление явных проверок состояния соединений перед запросами заняла полтора часа.

Почему один день вместо недели: роль агентов

Раньше установка такой системы у клиента — это как минимум 3-4 человека и неделя работы. Один занимается сервером и SSH-доступом, другой настраивает PostgreSQL и схему БД, третий пишет документацию и плейбук, четвёртый коммуницирует с клиентом и переспрашивает детали конфигурации. Плюс итерации между ними: нашли проблему — написали коллеге — получили ответ — попробовали — снова проблема. Каждый такой цикл занимает полдня минимум.

Здесь я один. Но у меня есть агенты, которые крутят рутину параллельно. Пока я диагностировал баг 3 с порядком запуска сервисов, агент готовил документацию по багам 1 и 2 для roadmap в правильном формате. Пока я искал корень бага 6 через asyncio debug mode, другой агент проверял остальные systemd-юниты на похожие паттерны инициализации. Это не ускорение в десять раз — это качественно другой процесс.

Ключевое: агенты не решают сложные технические задачи вместо меня. Они убирают весь overhead вокруг задачи. Не нужно переключаться между «сделать» и «записать» — запись происходит параллельно. Не нужно вручную оформлять баги в таск-трекер с правильными полями — они уже там. Не нужно искать похожие проблемы в старых логах — агент ищет, пока я работаю над текущим.

Результат: я занимался только тем, что требует реального технического мышления — диагностика, анализ stacktrace, понимание причин. Остальное — параллельно. Это и есть разница между «один человек» и «один человек плюс система». Подробнее о том, как это выглядит изнутри — в статье про агентов, которые работают в фоне молча.

Плейбук «как развернуть продукт до того, как баги пофиксены»

После шестого бага у меня был готовый файл deployment-bugs-azamat.md с 6 задокументированными проблемами, обходными путями и конкретными командами для каждого. Я превратил его в плейбук — инструкцию для следующей установки Telepilot у клиента.

Плейбук — это не документация кода и не release notes. Это список «что конкретно делать, если продукт ещё не идеален». Звучит странно, но это очень реальная потребность: клиент нужен сегодня, баги в roadmap на следующий спринт, установщик должен доставить рабочий результат прямо сейчас.

Структура получилась такой: для каждого известного бага — как проявляется (что видишь в логах или в поведении системы), причина в одном предложении, обходной путь с конкретными командами, статус (в roadmap Phase 5 / уже пофиксен / специфично для Debian). Четыре колонки, шесть строк.

Это работает лучше, чем «подождите, мы сначала починим все баги». Клиент получает работающую систему сейчас. Разработчик получает реальный кейс из production-окружения с воспроизводимыми шагами. Оба выигрывают. Следующий установщик не тратит день на диагностику — он тратит час на применение обходных путей по плейбуку. Это подход, про который я писал в статье про 5 ошибок при внедрении AI-автоматизации — «не ждать идеальной версии».

Что попало в roadmap Phase 5 и как изменился Telepilot после этого кейса

Все 6 багов стали конкретными задачами в Phase 5 roadmap. Это не просто список проблем — это изменения, которые делают продукт пригодным для установки у клиентов без ручного вмешательства в процессе.

Баги 1 и 4 — про скрипты деплоя: install.sh и deploy.sh будут переписаны с правильными guard-проверками и единообразными именами переменных окружения. DATABASE_URL везде и всегда, не DB_URL в одном файле и DATABASE_URL в другом. Баг 2 — про кросс-дистрибутивную совместимость: install.sh будет определять дистрибутив через /etc/os-release и выставлять правильный PYTHONPATH автоматически. Баг 3 — про systemd: уйдём от sleep к health-check с правильными Type= директивами. Баг 5 — про пакетирование: все модули, которые нужны при установке через pip, будут явно перечислены в packages= — никаких имплицитных зависимостей от расположения файлов. Баг 6 — фикс в 3 строки кода, уже готов к мержу.

После этих изменений установка Telepilot на чистый Ubuntu или Debian должна занимать 2-4 часа без дополнительных обходных путей. Это разумная цель для первой коммерческой версии продукта.

К обеду на сервере Азамата работали 5 чат-парсеров, подключённых к 130 чатам. Система мониторила активность в реальном времени, данные шли в базу PostgreSQL, фильтры отрабатывали корректно. То, что казалось двухчасовой задачей, заняло весь день. Зато теперь есть плейбук, 6 задач в roadmap и первый production-кейс за пределами Solar Property.

Самый дорогой баг — это баг, который ты диагностируешь дважды. Один раз у себя в разработке, второй раз когда его воспроизводит клиент и пишет тебе в панике в десять вечера. Документация по ходу работы — не бюрократия и не трата времени. Это экономия времени следующего себя и следующего клиента. Шесть багов за один день — это нормальное состояние любого продукта, который впервые выходит за пределы контролируемой среды разработки. Ubuntu против Debian, мои переменные окружения против чистой машины, мой порядок команд против чужого деплой-скрипта — всё это даёт разницу, которую не поймать никакими unit-тестами в изолированной среде.

Как выстроить процесс первой клиентской установки, чтобы не потерять день

После этого опыта у меня появился стандартный pre-flight список для любой новой установки Telepilot. Не потому что я стал осторожнее — а потому что каждый пункт в нём стоил мне конкретного времени в этот день.

Первое: уточнить дистрибутив и версию Python до начала. Не «Linux», а конкретно: Ubuntu 22.04 / Debian 12 / CentOS 9. Версия Python: 3.10 / 3.11 / 3.12. Это меняет несколько вещей в инструкции. На Debian 12 с Python 3.11 — применяем обходы для багов 2 и 6 сразу, не ждём пока они проявятся.

Второе: перед редактированием конфигов — сохранить копию. Звучит очевидно, пока deploy.sh не перетрёт твои правки второй раз подряд. Теперь у меня в плейбуке первая команда: cp config.yaml config.yaml.backup-$(date +%Y%m%d-%H%M%S). Одна строка, ноль потерянных изменений.

Третье: проверить имена всех переменных окружения до запуска миграций. Открыть deploy.sh и файл alembic.ini или env.py рядом, сверить построчно. Если есть расхождение — исправить в deploy.sh. Это занимает пять минут, экономит двадцать на диагностику.

Четвёртое: после запуска systemd-юнитов — не сразу проверять статус, а подождать 10-15 секунд. Сервисы с зависимостями поднимаются не мгновенно. Преждевременная проверка systemctl status может показать «failed» у сервиса, который ещё просто не успел стартовать. Это вводит в заблуждение и тратит время на диагностику несуществующей проблемы.

Пятое: тестировать соединение с базой отдельно от запуска всего стека. Одна команда — psql -U user -h host -d dbname -c "SELECT 1" — показывает, работает ли база, доступны ли права, правильный ли хост. Если это не работает — все остальные сервисы не поднимутся в любом случае, и незачем тратить время на их диагностику.

Этот список из пяти пунктов появился из одного неудачного дня. Следующая установка по нему заняла четыре часа вместо восьми, хотя версия продукта была та же самая — баги в roadmap ещё не пофиксены. Разница только в том, что я знал, где они будут, и применял обходы заранее, а не искал причину постфактум.

Telepilot как продукт продолжает развиваться. Phase 5 с исправлением всех 6 багов этого кейса выйдет в ближайшие недели. После этого установка у клиента будет занимать 2-3 часа без дополнительных плясок. Но даже сейчас — с плейбуком и пониманием подводных камней — это реально сделать за день в одиночку. Что я и доказал на сервере Азамата.

Частые вопросы

Что такое Telepilot и для каких задач он подходит?
Telepilot — система, которая разворачивает чат-парсеры в Telegram и позволяет мониторить сотни чатов одновременно без ручного просмотра. Подходит для бизнесов, которым нужно отслеживать упоминания, лиды, конкурентов или активность в больших группах. В кейсе Азамата — 5 парсеров, 130 чатов, данные собираются в реальном времени. Не подходит для разовых задач с малым количеством чатов — там проще ручной мониторинг.
Почему установка Telepilot на Debian дала 6 багов?
Ubuntu и Debian по-разному обрабатывают пути файлов, переменные systemd и модульную структуру Python-пакетов. Telepilot разрабатывался и тестировался в окружении Solar Property (Ubuntu), а у Азамата был Debian. Три из шести багов — именно про различия дистрибутивов: пути библиотек, поведение pip при установке пакетов, обработка переменных окружения в deploy.sh. Остальные три — логические ошибки в скрипте деплоя, которые не проявлялись в тестах на своём сервере.
Можно ли установить Telepilot самостоятельно без технических знаний?
Нет. На текущем этапе Telepilot требует доступа к серверу по SSH, умения работать с systemd, PostgreSQL и Python-окружениями. Это продукт для технарей или для установки командой Solar. Мы работаем над упрощённым вариантом деплоя, но пока в roadmap. Если у вас нет DevOps-компетенций — лучше заказать установку под ключ, чем тратить день на отладку.
Сколько времени занимает установка Telepilot у опытного специалиста?
После того как баги из этого кейса попали в roadmap и были исправлены — установка занимает 2-4 часа на чистом Ubuntu/Debian. До исправления — уходил полный рабочий день. Это первая установка за пределами Solar, поэтому каждый баг приходилось диагностировать с нуля, без опыта того, где искать.
Что значит плейбук для развёртывания до того как баги пофиксены?
Это документ с пошаговым обходом известных проблем для конкретной версии продукта. Не ждать идеального кода — написать 'вот баг 3, вот workaround, делай так'. Для Telepilot этот плейбук появился в день первой установки: каждый баг записан, обходной путь зафиксирован, следующий установщик уже не тратит время на диагностику.

Читайте также

Подписаться на блог в Telegram

Читайте свежие кейсы об AI-автоматизации, системной архитектуре и масштабировании бизнеса.

Подписаться