Давайте наглядно сравним, как вы обновляете бота сейчас и как будете это делать через 25 минут.
Представьте. Три часа ночи. На азиатской сессии происходит что-то невообразимое, и ваш бот из-за редкого бага начинает спамить ордерами. Вы просыпаетесь от алерта мониторинга. Сердце колотится. Нужно срочно выкатить фикс.
Вы быстро пишете исправление, тестируете локально — все работает. `git commit -m "HOTFIX: stop spamming orders"`, `git push`. И вот он, момент истины. Нужно доставить код на сервер.
Вы пытаетесь подключиться к серверу по SSH, а терминал выдает ошибку: `Permission denied (publickey)`. Внутри все холодеет. Вы вспоминаете, что пару дней назад переустанавливали систему на рабочем ноутбуке, а SSH-ключ для доступа к серверу остался на старом диске. Или на флешке. Или где?..
Пока вы в панике ищете бэкапы, бот продолжает терять деньги. Каждая секунда — это стресс и убытки. Вы находите старый ноутбук, пытаетесь загрузить его, он предательски долго обновляется...
В этот момент вы понимаете: должен быть способ лучше. Способ, который не зависит от того, где ваш SSH-ключ, и который не требует от вас быть ночным системным администратором для своего же проекта. Этот способ называется CI/CD.
Давайте забудем о коде на минуту. Представьте, что вы строите модели из LEGO. Ваш репозиторий — это чертежи и коробки с деталями.
А дальше начинается магия автоматизации, тот самый CI/CD:
GitHub Actions — это и есть тот самый «мозг» завода, который управляет всеми роботами по вашим чертежам (workflow-файлам).
Чтобы робот GitHub мог зайти на ваш сервер и обновить бота, ему нужен ключ. Мы не будем давать ему свой личный ключ. Вместо этого мы создадим отдельный, специальный ключ только для деплоя.
Шаг 1: На вашем локальном компьютере создаем новую пару SSH-ключей.
ssh-keygen -t ed25519 -f ~/.ssh/github-actions -C "github-actions-deploy"
Эта команда создаст два файла: `github-actions` (приватный ключ, никому не показывать!) и `github-actions.pub` (публичный ключ, им можно делиться).
Шаг 2: На вашем VPS-сервере, куда задеплоен бот, нужно «прописать» этот ключ. Сначала подключитесь к серверу как обычно.
Посмотрите содержимое публичного ключа на вашем локальном компьютере:
cat ~/.ssh/github-actions.pub
Скопируйте всю строку, которая начнется с `ssh-ed25519 ...`.
Теперь на сервере добавьте эту скопированную строку в файл `~/.ssh/authorized_keys`. Проще всего это сделать так:
echo "вставьте_сюда_скопированную_строку" >> ~/.ssh/authorized_keys
Готово. Теперь любой, у кого есть приватный ключ `github-actions`, сможет подключиться к вашему серверу от вашего имени. Этот ключ мы сейчас надежно спрячем.
Приватный ключ нельзя просто так положить в код. Для этого в GitHub есть раздел Secrets. Это зашифрованное хранилище, доступ к которому имеет только GitHub Actions.
Нам нужно создать три секрета:
Теперь наш робот знает, куда идти (`VPS_HOST`), как представиться (`VPS_USER`) и какой ключ показать (`SSH_PRIVATE_KEY`).
Время создать инструкцию для нашего робота. В корне вашего проекта создайте папку `.github`, а в ней — папку `workflows`. Внутри создайте файл `deploy.yml`.
Путь должен быть таким: `.github/workflows/deploy.yml`.
Вставьте в этот файл следующий код. Комментарии в коде объясняют каждый шаг.
# Название нашего workflow, будет отображаться в интерфейсе GitHub
name: Deploy Trading Bot
# Триггер: запускать этот workflow при каждом push в ветку 'main'
on:
push:
branches: [ main ]
# Задачи, которые нужно выполнить
jobs:
deploy:
# Название задачи, тоже для интерфейса
name: Deploy to VPS
# На каком виртуальном компьютере выполнять (стандартный Ubuntu от GitHub)
runs-on: ubuntu-latest
# Шаги, которые нужно выполнить последовательно
steps:
# 1. Клонируем наш репозиторий на виртуальную машину Runner'а
- name: Checkout code
uses: actions/checkout@v3
# 2. Настраиваем SSH-агент, чтобы он мог использовать наш ключ
# Этот экшен берет приватный ключ из секрета и делает его доступным для SSH-команд
- name: Setup SSH
uses: webfactory/ssh-agent@v0.7.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
# 3. Выполняем команды на удаленном сервере
# Это сердце нашего workflow
- name: SSH to VPS and deploy
run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} '
echo ">>> Connected to VPS"
# Переходим в папку с проектом
cd /home/ubuntu/my-trading-bot
echo ">>> Changed directory to project folder"
# Вытягиваем последние изменения из main ветки
git pull origin main
echo ">>> Pulled latest changes from git"
# Скачиваем новые образы, если они есть
docker-compose pull
echo ">>> Pulled new docker images"
# Перезапускаем контейнеры в фоновом режиме
# --force-recreate гарантирует, что контейнер будет пересоздан с новым образом
docker-compose up -d --force-recreate
echo ">>> Restarted docker containers"
# Очищаем старые, неиспользуемые образы, чтобы не занимать место
docker image prune -f
echo ">>> Pruned old docker images"
echo ">>> Deployment finished!"
'
Важно: Замените путь `cd /home/ubuntu/my-trading-bot` на ваш реальный путь к проекту на сервере.
Теперь сохраните этот файл, сделайте `git add .`, `git commit -m "Add CI/CD workflow"` и `git push`. Зайдите на вкладку "Actions" в вашем репозитории на GitHub — вы увидите, как ваш первый автоматический деплой выполняется в реальном времени!
Наш конвейер работает, но он пока не очень умный — он доставляет на сервер любой код. Давайте добавим шаг проверки качества. Если у вас есть тесты (например, на pytest), их можно запускать перед деплоем.
Добавьте этот шаг в `deploy.yml` перед шагом "SSH to VPS and deploy":
# ... после шага 'Checkout code'
- name: Setup Python and run tests
uses: actions/setup-python@v4
with:
python-version: '3.10'
- run: pip install pytest
- run: pytest # или ваша команда для запуска тестов/бэктеста
# ... дальше идет шаг 'Setup SSH' и 'SSH to VPS and deploy'
Теперь, если тесты провалятся, весь workflow остановится. Код с ошибками просто не доедет до вашего сервера. Это ваша страховка от случайных багов.
Автоматизация — это прекрасно, но что, если вы выкатили неработающее обновление? Паниковать и лезть на сервер? Нет. У нас есть элегантный план.
Git предоставляет команду `git revert [commit-hash]`. Она не удаляет историю, а создает новый коммит, который отменяет изменения проблемного коммита.
Ваш план действий:
И ваш автоматический конвейер сам за вас все исправит: он увидит новый коммит (откатывающий), запустит workflow и развернет на сервере предыдущую, рабочую версию кода. Никакого SSH, никакой паники.
Приятно знать, когда деплой завершен (успешно или нет). Давайте научим робота отчитываться в Telegram. Для этого тоже есть готовый Action.
Сначала добавьте в GitHub Secrets еще два секрета: `TELEGRAM_BOT_TOKEN` и `TELEGRAM_CHAT_ID`.
Затем добавьте в конец файла `deploy.yml` (внутри `steps`) следующий блок:
# ... после шага 'SSH to VPS and deploy'
- name: Send Telegram notification
# Этот шаг будет выполняться всегда, независимо от успеха или провала предыдущих
if: always()
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_CHAT_ID }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
message: |
🚀 Deploy for ${{ github.repository }} finished!
Status: ${{ job.status }}
Commit: ${{ github.event.head_commit.message }}
See details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
Теперь после каждого деплоя вам в Telegram будет приходить красивый отчет.
Поздравляю! Вы только что настроили настоящий автопилот для своего проекта. Теперь ваш деплой — это одна команда: `git push`. Вы сэкономили себе часы времени и килограммы нервных клеток.
Ваш бот работает под присмотром Nginx, Grafana, с бэкапами в Backblaze и теперь обновляется автоматически. Это уже серьезная, надежная система.
Но что, если у вас не один бот, а пять? Десять? Вы хотите запустить одну и ту же стратегию на разных парах, или несколько разных стратегий. Создавать для каждого отдельный VPS? Копировать репозиторий и workflow? Неэффективно.
В следующем уроке мы решим эту проблему. Мы превратим нашего одинокого бота в управляемый «рой». Мы научимся управлять целым флотом ботов на одном сервере как единым организмом, используя всю мощь Docker Compose.
Хочешь больше? Полный курс AI Agents включает Production-модуль + 27 других уроков
AI Agents $199 →