Это готовый шаблон для создания Telegram-бота на Python (aiogram 3) с полностью автоматизированным процессом развёртывания (CI/CD) с помощью GitHub Actions и Docker.
- Автоматизация "под ключ": Настройте сервер один раз, и каждый
pushвmainветку будет автоматически обновлять вашего бота. - Docker: Бот упакован в Docker-контейнер, что обеспечивает изоляцию и воспроизводимость окружения.
- GitHub Actions: Готовые workflow для сборки, тестирования, публикации и деплоя вашего бота.
- Безопасность:
- Создание отдельного пользователя на сервере с ограниченными правами.
- Доступ к серверу по SSH-ключам (вход по паролю отключается).
- Использование
WEBHOOK_SECRETдля верификации запросов от Telegram.
- Надёжность:
- Скрипт настройки автоматически устанавливает все зависимости (
docker,sudo,curl). healthcheckдля автоматического перезапуска "заболевшего" контейнера.restart: unless-stoppedдля автоматического запуска бота после перезагрузки сервера.
- Скрипт настройки автоматически устанавливает все зависимости (
- Простота настройки: Интерактивный скрипт
bootstrap-server-custom.shпроведёт вас по всей первоначальной настройке сервера. - HTTPS "из коробки": Инструкции по настройке реверс-прокси Caddy для автоматического получения и обновления SSL-сертификатов.
- Сервер: Любой VPS/VDS с публичным IP-адресом и Ubuntu 22.04 (или другой Debian-based дистрибутив).
- Доменное имя: Домен или поддомен, A-запись которого указывает на IP-адрес вашего сервера.
- Аккаунт GitHub: Для хранения кода и использования GitHub Actions.
- Токен Telegram-бота: Полученный от @BotFather.
- Склонируйте этот репозиторий или используйте его как шаблон (
Use this template). - Загрузите код в ваш собственный репозиторий на GitHub.
Это самый важный шаг, который выполняется только один раз.
-
Подключитесь к вашему серверу по SSH. Вам понадобятся права суперпользователя (
root). -
Запустите скрипт настройки одной командой. Скрипт должен выполняться от имени
root(например, черезsudoили после входа какroot). Он автоматически установит все необходимые зависимости (включаяdocker,curlиsudo), если они отсутствуют в системе.Вам нужно передать только
GITHUB_REPOSITORY. Скрипт задаст остальные вопросы.# Запустите с sudo, или без него, если вы уже root sudo GITHUB_REPOSITORY="your-username/your-repo" \ bash -c "$(curl -fsSL https://raw.githubusercontent.com/your-username/your-repo/main/deploy/bootstrap-server-custom.sh)"
Вы можете передать все параметры через переменные окружения для полностью автоматической установки.
# Запустите с sudo, или без него, если вы уже root sudo GITHUB_REPOSITORY="your-username/your-repo" \ BOT_NAME="my_cool_bot" \ DEPLOY_USER="bot_runner" \ WEBHOOK_HOST_URL="https://bot.example.com" \ HOST_PORT="8001" \ bash -c "$(curl -fsSL https://raw.githubusercontent.com/your-username/your-repo/main/deploy/bootstrap-server-custom.sh)"
Описание переменных:
GITHUB_REPOSITORY(обязательно): Путь к вашему репозиторию (user/repo).BOT_NAME(опционально): Имя для бота и контейнера (по умолчанию:bot_main).DEPLOY_USER(опционально): Имя пользователя на сервере (по умолчанию: значениеBOT_NAME).WEBHOOK_HOST_URL(опционально): Публичный URL для вебхука. Если не указан, скрипт спросит его.HOST_PORT(опционально): Внешний порт на сервере (по умолчанию:8001).
После выполнения скрипт выведет данные, которые понадобятся на следующем шаге.
Скрипт вывел на экран все необходимые данные. Их нужно добавить в ваш репозиторий на GitHub.
- Перейдите в репозиторий на GitHub:
Settings>Secrets and variables>Actions. - Нажмите
New repository secretи добавьте следующие секреты:SSH_HOST: Публичный IP-адрес вашего сервера (из вывода скрипта).SSH_USER: Имя пользователя, созданного скриптом (из вывода скрипта).SSH_PRIVATE_KEY: Приватный SSH-ключ для деплоя (из вывода скрипта). Важно: скопируйте ключ полностью, включая строки-----BEGIN...и-----END...и пустую строку в конце.CLEANUP_COMMAND: Команда для полного удаления бота с сервера (из вывода скрипта).BOT_TOKEN: Токен вашего Telegram-бота, полученный от @BotFather.
Чтобы ваш бот был доступен по HTTPS, нужен реверс-прокси. Скрипт уже сгенерировал для вас готовую конфигурацию для Caddy.
- Установите Caddy на сервер (если ещё не установлен):
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list sudo apt update sudo apt install caddy
- Откройте файл
Caddyfile:sudo nano /etc/caddy/Caddyfile
- Вставьте в него блок конфигурации, который вывел bootstrap-скрипт. Он выглядит примерно так:
your-bot.example.com { reverse_proxy localhost:8001 } - Перезапустите Caddy, чтобы применить изменения:
sudo systemctl reload caddy
Всё готово! Теперь просто сделайте коммит и отправьте изменения в main ветку вашего репозитория.
git add .
git commit -m "Final setup"
git push origin mainGitHub Actions автоматически запустит workflow, соберёт Docker-образ, загрузит его в GHCR и развернёт на вашем сервере. Через несколько минут ваш бот будет онлайн!
При первом деплое или после смены домена вы можете столкнуться с ошибкой в логах контейнера, которая выглядит примерно так:
Failed to set webhook: ... Bad Request: bad webhook: Failed to resolve host: Temporary failure in name resolution
Эта ошибка означает, что серверы Telegram не могут "найти" ваш домен в сети Интернет. Когда вы создаете или изменяете A-запись для вашего домена, требуется время (от нескольких минут до нескольких часов), чтобы эта информация распространилась по всем DNS-серверам мира. Этот процесс называется DNS-пропагацией. Скрипт entrypoint.sh ждет, пока домен станет доступен с вашего сервера, но это не гарантирует, что серверы Telegram уже его "увидели".
-
Подождите. В большинстве случаев проблема решается сама собой через 15-30 минут.
-
Проверьте доступность домена вручную. Откройте ваш домен (
https://your-bot.example.com) в браузере. Если вы видите пустую страницу или ответ от Caddy (а не ошибку "Сайт не найден"), значит, DNS-запись уже работает как минимум для вас. -
Проверьте установку вебхука через API Telegram. Это самый надежный способ диагностики. Выполните следующие шаги прямо в адресной строке браузера, заменяя
<ВАШ_BOT_ТОКЕН>и<ВАШ_WEBHOOK_URL>на свои значения.Шаг 1: Проверьте текущий статус Откройте URL, чтобы узнать, что Telegram "думает" о вашем вебхуке:
https://api.telegram.org/bot<ВАШ_BOT_ТОКЕН>/getWebhookInfoОбратите внимание на поле
last_error_message, если оно есть.Шаг 2: Удалите старый вебхук (для чистоты эксперимента)
https://api.telegram.org/bot<ВАШ_BOT_ТОКЕН>/deleteWebhookВы должны получить ответ
{"ok":true,"result":true,"description":"Webhook was deleted"}.Шаг 3: Попробуйте установить вебхук заново
https://api.telegram.org/bot<ВАШ_BOT_ТОКЕН>/setWebhook?url=<ВАШ_WEBHOOK_URL>- Если вы получите ответ
{"ok":true,"result":true,"description":"Webhook was set"}, значит, всё в порядке. Проблема решена, и следующий деплой должен пройти успешно. - Если вы снова увидите ошибку
Temporary failure in name resolutionв ответе, значит, DNS-пропагация еще не завершилась, и нужно подождать.
- Если вы получите ответ
.github/workflows/deploy.yml: Файл workflow для GitHub Actions..github/workflows/cleanup.yml: Файл workflow для удаления бота с сервера.deploy/bootstrap-server-custom.sh: Скрипт для первоначальной настройки сервера.deploy/cleanup-server.sh: Скрипт для полного удаления бота с сервера.bot.py: Основной файл с логикой бота (aiogram).Dockerfile: Инструкции для сборки Docker-образа.docker-compose.yml: Файл для управления контейнером на сервере (создаётся скриптом)..env: Файл с переменными окружения (создаётся скриптом).requirements.txt: Список Python-зависимостей.