Надёжность, секреты и деньги

Наутро после запуска отчёта таймер сработал вовремя, отчёт пришёл. Я открыл журнал отчёта, чтобы просто убедиться, и увидел в нём токен бота «Кодиума» открытым текстом. Агент за восемь заданий этого ни разу не заметил. Урок про то, что ломается и протекает в интеграциях, и про деньги: как объяснить заказчику, что автоматизация окупается.

Чему научишься в этом уроке:
• найти секрет в журнале и убрать его оттуда;
• закрыть сервер от сканеров и подбора пароля;
• понять, что форма делает при сбое, и где смотреть, что заявка не дошла;
• посчитать заказчику окупаемость и сравнить абонплату n8n с сервером.

Токен в журнале

Журнал службы похож на бортовой журнал корабля: туда пишется всё, что происходило. Читают его ты, наставник, а иногда и тот, кому ты дал доступ к серверу. Библиотека httpx, через которую программа ходит в интернет, на обычном уровне подробности записывала каждый запрос целиком, вместе с адресом. А в адресе запроса к Telegram стоит токен бота:

HTTP Request: POST https://api.telegram.org/bot<токен>/sendMessage

Кто видит токен, тот управляет ботом. Задание агенту на починку (адрес сервера заменён):

Утечка секрета: в журнале отчёта (journalctl -u kodium-otchet) библиотека httpx пишет строку «HTTP Request: POST https://api.telegram.org/bot<ТОКЕН>/sendMessage» — токен бота лежит в журнале открытым текстом. Почини во ВСЕХ частях проекта (бот, форма, отчёт): уровень логгеров httpx и httpcore — WARNING, и нигде не логировать URL с токеном. Добавь тест, что при отправке в Telegram токен не попадает в лог. Выложи на сервер <адрес сервера>, перезапусти bot-kodium и kodium-forma, запусти kodium-otchet один раз вручную и покажи, что в журнале больше нет строк с api.telegram.org/bot. Старые записи журнала с токеном удали: journalctl --rotate и journalctl --vacuum-time=1s.

Уровень WARNING значит «пиши только предупреждения и ошибки», обычные запросы в журнал больше не попадают. За 5,1 минуты агент починил все три части, строк с api.telegram.org/bot в журнале стало 0. Учти: команда journalctl --vacuum-time=1s стирает журналы ВСЕХ служб сервера, а не только строки с токеном. Для учебного сервера это нормально, на сервере заказчика сначала согласуй.

Токен уже побывал в журнале, поэтому считаем его раскрытым и перевыпускаем у @BotFather командой /revoke. Новый токен вписываешь сам: зайди ssh root@<адрес сервера>, открой файл командой nano /opt/bot-kodium/.env, замени значение токена, сохрани (Ctrl+O, Enter, Ctrl+X) и перезапусти службы: systemctl restart bot-kodium kodium-forma. Если собирал n8n, замени токен и в учётных данных «T1 бот Кодиум».

Правило: после любой выкладки прочитай журнал глазами. Проверить быстро можно так: journalctl -u kodium-otchet | grep api.telegram.org/bot. grep это команда поиска строки в тексте. Пустой вывод значит, что токена там нет.

Сканеры и подбор пароля

Как только у сервера появился домен и открытые порты 80 и 443, к нему пришли гости. В журнале доступа nginx видно, как чужие программы-сканеры перебирают адреса вроде /functions/.env. Они ищут забытый файл с секретами, который кто-то положил в папку сайта. Наш .env лежит в папке проекта, nginx её не отдаёт, поэтому сканеры получают отказ. Держи так и дальше: секреты никогда не кладутся туда, откуда сервер отдаёт страницы.

Второе наблюдение из прогона: в журнале входа на сервер (auth.log) через сутки после создания уже были попытки подобрать пароль root с чужих адресов. Ты входишь по ключу, поэтому вход по паролю лучше выключить совсем: настройка PasswordAuthentication no (вход по паролю: нет). Задание агенту (текст курса, в прогоне это не выполняли):

Отключи на сервере <адрес сервера> вход по паролю: PasswordAuthentication no. Проверь, не перебивает ли эту настройку файл в /etc/ssh/sshd_config.d/, итог покажи командой sshd -T | grep passwordauthentication. Перезапусти ssh. Текущую сессию не закрывай, пока я не проверю вход по ключу во ВТОРОЙ сессии.

Открой второе окно терминала и войди по ключу как обычно. Получилось, тогда первую сессию можно закрывать. Проверить, что пароль больше не принимают: ssh -o PubkeyAuthentication=no root@<адрес сервера> должен ответить Permission denied (в доступе отказано).

Схема сервера «Кодиума» с дверями: 443 (HTTPS) открыта — через неё идут заявки Яндекс Формы, сканер с запросом /functions/.env получает 404; 22 (SSH) только по ключу — подбор пароля root не проходит; остальные закрыты. Внутри: папка сайта nginx без секретов и папка проекта /opt/bot-kodium с .env. Ниже настоящий вывод ufw status: OpenSSH, 80/tcp, 443/tcp разрешены для IPv4 и IPv6.

Что делает форма при сбое

Сервис может упасть ночью, сервер может перезагружаться. Яндекс Формы к этому готовы: ждут ответа 5 секунд, а если ответа нет, сервер ответил ошибкой 5XX или 404, повторяют отправку до 7 раз за 30 минут. Поэтому в задании на приём формы мы просили отвечать быстро, а выгрузку на Диск делать уже после ответа.

Где смотреть, дошла ли заявка: в форме на вкладке «Интеграции → Выполненные интеграции». Там видно каждую отправку и её результат, неудачную можно перезапустить. В n8n то же самое показывает список запусков сценария: success или ошибка. В коде смотри журнал службы kodium-forma.

Есть и обратная сторона повторов. Если сервис заявку сохранил, но ответил дольше 5 секунд, форма может прислать её ещё раз, и в файле появится дубль. В прогоне такого не ловили, но держи это в голове: если в файле две одинаковые заявки подряд, загляни в «Выполненные интеграции».

Что ломается и как узнать

  • Запустил certbot заново, например на новый домен → nginx может снова начать слушать только IPv4, как было в прогоне после первой установки (урок 3.3). Проверка: curl -6 на свой адрес должен отвечать 200.
  • Токен Яндекс Диска отозвали или сменили права → выгрузка в файл падает, заявка остаётся в запасном pending.jsonl из П1. Проверка: журнал службы.
  • Форму поменяли и убрали параметры → приходят пустые данные, сервис честно отвечает 400. Проверка: «Выполненные интеграции».
  • Сертификат Let’s Encrypt не продлился → форма перестанет достучаться. Дату окончания ты видел при установке в уроке 3.3.

Для заказчика собери всё это на одну страницу: что может сломаться, по каким признакам это видно, кому писать. Об устройстве повторов в n8n подробнее в уроке трека 2 про надёжность.

Деньги: окупаемость для заказчика

Цену интеграции объясняем сэкономленным временем. Пример из материалов курса: менеджер тратит 2 часа в день на перенос заявок и сводку, час его работы стоит 300 ₽. За 20 рабочих дней это 40 часов, то есть 12 000 ₽ в месяц. Если интеграция стоит 40 000 ₽, она окупится чуть больше чем за три месяца.

Ориентир по цене таких работ из материалов курса: 20–60 тысяч ₽ за настройку и 3–5 тысяч ₽ в месяц за поддержку. Это ориентир, а не обещание: смотри, сколько сэкономит именно твой заказчик.

Отдельно заказчик платит за то, на чём всё крутится. Вот сравнение на 09.10.2026:

  • Код на своём сервере. Абонплаты за сценарии нет. Сервер Timeweb из П1: цену своего тарифа смотри в счёте Timeweb. Для ориентира: в фактах курса самый дешёвый видимый тариф 900 ₽ в месяц при оплате за год, но это 2 ядра, а у сервера из прогона 1 ядро. Бот и приём формы живут на одном сервере.
  • n8n в облаке. Starter 20 € в месяц при оплате за год, 2 500 запусков; Pro 50 € в месяц при оплате за год, 10 000 запусков. Запуск это один прогон сценария, сколько бы в нём ни было шагов. Оплата в евро; какие карты принимают, мы не проверяли.

Посчитай запуски для «Кодиума»: каждая заявка с формы это один запуск, плюс один отчёт в день, около 30 в месяц. До 2 500 запусков малой школе далеко.

И твой собственный расход. В прогоне задания агенту на путь «код» заняли около 40 минут его работы за 8 заданий, от 1,1 до 11 минут каждое, и около 0,35 $ в CloseRouter (примерно 30 ₽ при условном курсе 90 ₽ за доллар). Свои деньги за модель смотри в кабинете CloseRouter.

Если не получилось

  • grep по журналу находит api.telegram.org/bot → уровень логгеров httpx и httpcore не поднят до WARNING в какой-то из частей проекта; проверь все три службы.
  • После выключения входа по паролю не пускает по ключу → не закрывай старую сессию, пока не проверил вход в новом окне.
  • В файле две одинаковые заявки подряд → смотри «Выполненные интеграции»: скорее всего, форма повторила отправку.

Контрольный вопрос. Ты выполнил grep по журналу отчёта и нашёл строку с api.telegram.org/bot и токеном. Что сделать кроме починки логирования?

АНичего, после починки новые строки не появятся
БПерезагрузить сервер
ВСменить пароль root
ГУдалить старые записи журнала и перевыпустить токен у @BotFather

Подсказка: Токен уже был виден. Можно ли считать его тайным?

На курсе задания проверяются автоматически. Решить первое задание бесплатно →  ·  Подобрать курс

Контрольный вопрос. Сервис формы лежал 10 минут ночью. Что стало с заявками, отправленными в это время?

АПропали навсегда
БФорма повторит отправку, результат видно в «Выполненных интеграциях»
ВСохранились в Яндекс Таблицах
ГПришли владельцу на почту

Подсказка: Сколько раз и за какое время Яндекс Формы повторяют запрос?

На курсе задания проверяются автоматически. Решить первое задание бесплатно →  ·  Подобрать курс

Контрольный вопрос. Менеджер тратит на ручной перенос 2 часа в день, час стоит 300 ₽, рабочих дней 20. Интеграция стоит 40 000 ₽. За сколько месяцев она окупится, если округлить вверх?

А2
Б3
В4
Г6

Подсказка: Сначала посчитай экономию в месяц, потом раздели цену на неё.

На курсе задания проверяются автоматически. Решить первое задание бесплатно →  ·  Подобрать курс

Задание. МИССИЯ «Чистый журнал и страница для заказчика». 1. Проверь журналы всех своих служб (бот, форма, отчёт) командой grep на api.telegram.org/bot. В n8n проверь, что токены лежат только в учётных данных, а не в тексте узлов. 2. Если нашёл токен: почини логирование заданием из урока, удали старые записи журнала, перевыпусти токен у @BotFather и сам положи новый в .env. 3. Выключи вход по паролю заданием из урока, проверь вход по ключу во второй сессии и отказ ssh -o PubkeyAuthentication=no. 4. Напиши для заказчика страницу «Что может сломаться»: 4 пункта «признак → где смотреть → что делать». 5. Посчитай окупаемость для своего заказчика по образцу урока. Принято, если: приложен снимок пустого вывода grep по журналам (или снимок учётных данных n8n без значений); снимок ответа Permission denied; текст страницы «Что может сломаться»; расчёт окупаемости с исходными числами.

Подсказка: Начни с журнала отчёта: в прогоне токен нашёлся именно там.

✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.

На курсе задания проверяются автоматически. Решить первое задание бесплатно →  ·  Подобрать курс

Что дальше

Техника готова, деньги посчитаны. Но заказ начинается раньше, с разговора с владельцем. В следующем уроке учимся вести созвон-диагностику и задавать вопрос, который решает, делать интеграцию кодом или в n8n.

Итог:
• в журналах нет секретов, раскрытый токен перевыпущен;
• вход на сервер только по ключу, секреты не в папке сайта;
• ты знаешь, где видно, что заявка не дошла, и умеешь посчитать заказчику окупаемость.

← Назад  ·  ↑ В начало урока  ·  ⌂ В начало курса  ·  Вперёд →

Школа Виктора Комлева