← НАЗАД К КУРСУ Этап 4 · Урок 3 из 5

Урок 4.3 — Сервер и деплой

Бот работает. Помнит разговоры. Но только пока открыт терминал на твоём компьютере. Закрыла ноутбук — бот уснул. Ушла спать — бот не отвечает. В этом уроке мы перенесём бота на удалённый сервер, который работает 24/7. После этого бот будет доступен всегда — даже когда ты не за компьютером.


Что такое сервер

Сервер — это обычный компьютер, который стоит в дата-центре и работает без перерывов. У него нет монитора, клавиатуры и мышки — только интернет. Управляешь им удалённо, через терминал.

Твой ноутбук                         Сервер (Hetzner)
┌──────────────┐                     ┌──────────────┐
│ Ты пишешь    │  ── SSH-команды ──► │ Linux-машина │
│ команды      │                     │ работает 24/7│
│ в терминале  │  ◄── ответы ──────  │ без монитора │
└──────────────┘                     └──────────────┘
                                     Адрес: 89.167.18.198

VPS (Virtual Private Server) — виртуальный сервер. Один физический компьютер делится на несколько виртуальных. Каждый работает независимо, как отдельная машина. Это дешевле, чем покупать свой сервер.

Популярные хостинги: Hetzner, DigitalOcean, Linode, Vultr. Цены от $4-10/месяц.


Шаг 1: Подключиться к серверу (SSH)

SSH (Secure Shell) — протокол для безопасного управления удалённым компьютером. Все команды и данные шифруются.

Открой терминал на своём компьютере и подключись:

ssh root@89.167.18.198

Введи пароль (символы не отображаются — это нормально). После этого ты внутри сервера.

Как понять, что ты на сервере?

Командная строка изменится:

# На своём компьютере:
katya@MacBook ~ %

# На сервере:
root@server:~#

Если видишь root@server — все команды выполняются на сервере, а не на ноутбуке.

Базовые команды Linux

На сервере обычно стоит Linux (Ubuntu). Вот минимум команд:

Команда Что делает Пример
pwd Показать текущую папку /root
ls Список файлов ls -la (с деталями)
cd Перейти в папку cd /home/botuser
cat Показать содержимое файла cat .env
nano Редактор текста nano bot.py (Ctrl+O сохранить, Ctrl+X выйти)
mkdir Создать папку mkdir mybot
rm Удалить файл rm old_file.py
exit Отключиться от сервера

Эти команды ты уже знаешь из урока 1.1 (терминал) — они те же самые.


Шаг 2: Подготовить сервер

Обновить систему

apt update && apt upgrade -y

apt — менеджер пакетов в Linux (как pip для Python, но для всей системы). update — обновить список доступных пакетов. upgrade — установить обновления.

Установить Python и инструменты

apt install -y python3-pip python3-venv git

Проверь, что Python установлен:

python3 --version

Шаг 3: Создать отдельного пользователя

На сервере по умолчанию ты — root (суперадминистратор). Root может всё: удалить любой файл, остановить любую службу. Это опасно: если в боте ошибка или уязвимость — злоумышленник получит полный контроль над сервером.

Решение — создать отдельного пользователя с ограниченными правами:

adduser botuser

Введи пароль для нового пользователя. Остальные вопросы (имя, телефон) — просто нажимай Enter.

Теперь бот будет работать от имени botuser — даже если что-то пойдёт не так, он не сможет навредить всей системе.


Шаг 4: Загрузить код на сервер

Есть два способа. Рекомендую второй (через git).

Способ A: Git (рекомендуется)

Если код уже на GitHub:

# Переключиться на пользователя botuser
su - botuser

# Склонировать репозиторий
git clone https://github.com/твой-юзернейм/my-telegram-bot.git
cd my-telegram-bot

Способ B: scp (прямое копирование)

Если кода нет на GitHub — скопируй файлы напрямую. Эту команду запускай на своём компьютере (не на сервере!):

scp -r ~/Desktop/my-telegram-bot/ root@89.167.18.198:/home/botuser/

scp — Secure Copy. Работает через SSH, данные шифруются.


Шаг 5: Настроить окружение

Виртуальное окружение (venv)

Из урока 1.1 ты знаешь, что venv — изолированная среда для пакетов Python. На сервере это обязательно — иначе пакеты бота могут конфликтовать с системными.

# Внутри папки проекта (/home/botuser/my-telegram-bot):
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
deactivate

Файл .env

Создай .env на сервере вручную (токены нельзя хранить в git):

nano /home/botuser/my-telegram-bot/.env

Впиши:

TELEGRAM_BOT_TOKEN=4839574812:AAFD39kkdpWt3ywyRZergyOLMaJhac60qc
ANTHROPIC_API_KEY=sk-ant-api03-...

Сохрани: Ctrl+OEnterCtrl+X.

Ограничь доступ к файлу (чтобы только владелец мог читать):

chmod 600 /home/botuser/my-telegram-bot/.env

Шаг 6: Проверить, что бот работает

Прежде чем настраивать автозапуск — убедись, что бот вообще запускается:

cd /home/botuser/my-telegram-bot
source venv/bin/activate
python3 ai_bot.py

Если видишь "Бот запущен!" и бот отвечает в Telegram — всё работает. Останови его: Ctrl+C.


Шаг 7: Сделать бота постоянным (systemd)

Проблема: почему бот умирает

Когда ты закрываешь SSH-соединение, сервер посылает сигнал "отключись" (SIGHUP) всем программам, запущенным в этой сессии. Твой бот — одна из них. Он получает сигнал и выключается.

Решение: systemd

systemd — это менеджер служб Linux. Он встроен в систему, ничего устанавливать не нужно. systemd умеет:

Создание сервиса

Вернись под пользователя root:

exit  # выйти из botuser обратно в root

Создай файл сервиса:

nano /etc/systemd/system/telegram-bot.service

Вставь это содержимое:

[Unit]
Description=Telegram AI Bot
After=network.target

[Service]
Type=simple
User=botuser
WorkingDirectory=/home/botuser/my-telegram-bot
ExecStart=/home/botuser/my-telegram-bot/venv/bin/python3 /home/botuser/my-telegram-bot/ai_bot.py
EnvironmentFile=/home/botuser/my-telegram-bot/.env
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Что значит каждая строка

Строка Зачем
Description=Telegram AI Bot Описание (для тебя)
After=network.target Ждать, пока появится интернет
User=botuser Запускать от botuser, НЕ от root
WorkingDirectory=... Рабочая папка бота
ExecStart=... Путь к Python из venv + путь к скрипту
EnvironmentFile=... Загрузить переменные из .env
Restart=always Перезапускать при любом сбое
RestartSec=10 Ждать 10 секунд перед перезапуском
WantedBy=multi-user.target Запускаться при нормальной загрузке сервера

Важно: в ExecStart указан Python из venv, а не системный. Это гарантирует, что бот использует правильные пакеты.

Запуск сервиса

systemctl daemon-reload    # перечитать файлы сервисов
systemctl enable telegram-bot    # включить автозапуск при загрузке
systemctl start telegram-bot     # запустить прямо сейчас

Проверка

systemctl status telegram-bot

Если видишь Active: active (running) — бот работает:

● telegram-bot.service - Telegram AI Bot
     Loaded: loaded (/etc/systemd/system/telegram-bot.service; enabled)
     Active: active (running) since Wed 2024-01-15 10:30:00 UTC
   Main PID: 1234 (python3)
     Memory: 52.0M

Теперь можешь закрыть SSH. Бот продолжит работать.


Управление ботом

Основные команды

systemctl start telegram-bot     # запустить
systemctl stop telegram-bot      # остановить
systemctl restart telegram-bot   # перезапустить
systemctl status telegram-bot    # проверить статус

Просмотр логов

# Все логи бота
journalctl -u telegram-bot

# Последние 50 строк
journalctl -u telegram-bot -n 50

# Следить за логами в реальном времени (как tail -f)
journalctl -u telegram-bot -f

# Логи за последний час
journalctl -u telegram-bot --since "1 hour ago"

journalctl — инструмент для чтения логов systemd. Флаг -u — по имени сервиса. Флаг -f — следить в реальном времени (для отладки).

Обновление бота

Когда ты изменила код и запушила в GitHub:

# На сервере:
su - botuser                    # переключиться на пользователя бота
cd /home/botuser/my-telegram-bot
git pull                         # скачать новый код
source venv/bin/activate
pip install -r requirements.txt  # если добавились новые пакеты
deactivate
exit                             # обратно в root

systemctl restart telegram-bot   # перезапустить с новым кодом
systemctl status telegram-bot    # убедиться, что работает

Безопасность: минимум

1. Не запускай бота от root

Мы уже это сделали — создали botuser и указали User=botuser в сервисе.

2. SSH-ключи вместо паролей

Пароли можно подобрать (брутфорс). SSH-ключи — нет.

На своём компьютере:

# Создать ключ (один раз)
ssh-keygen -t ed25519 -C "my-server-key"
# Нажми Enter (оставь путь по умолчанию)
# Введи пароль для ключа (или просто Enter)

# Скопировать ключ на сервер
ssh-copy-id root@89.167.18.198

После этого ssh root@89.167.18.198 работает без пароля — используется ключ.

Как это работает: у тебя два файла — приватный ключ (на компьютере, никому не показывать) и публичный ключ (на сервере). Это как замок и ключ: публичный ключ — это замок, приватный — ключ от него.

3. Файрвол (ufw)

Файрвол блокирует все входящие подключения, кроме разрешённых.

ufw allow OpenSSH    # ОБЯЗАТЕЛЬНО — разрешить SSH, иначе потеряешь доступ!
ufw enable           # включить файрвол
ufw status           # проверить правила

Для Telegram-бота, который использует polling, не нужно открывать дополнительные порты. Бот сам обращается к Telegram (исходящее соединение), а не принимает подключения.


Полный чек-лист деплоя

Подготовка сервера:
  [ ] ssh root@89.167.18.198
  [ ] apt update && apt upgrade -y
  [ ] apt install -y python3-pip python3-venv git
  [ ] adduser botuser

Безопасность:
  [ ] ufw allow OpenSSH && ufw enable

Загрузка кода:
  [ ] su - botuser
  [ ] git clone https://github.com/.../my-telegram-bot.git
  [ ] cd my-telegram-bot

Настройка:
  [ ] python3 -m venv venv
  [ ] source venv/bin/activate && pip install -r requirements.txt && deactivate
  [ ] nano .env (вписать токены)
  [ ] chmod 600 .env

Проверка:
  [ ] source venv/bin/activate && python3 ai_bot.py (работает? Ctrl+C)
  [ ] exit (обратно в root)

Автозапуск:
  [ ] nano /etc/systemd/system/telegram-bot.service
  [ ] systemctl daemon-reload
  [ ] systemctl enable telegram-bot
  [ ] systemctl start telegram-bot
  [ ] systemctl status telegram-bot → active (running) ✓

Частые ошибки

1. Бот не запускается через systemd

Проблема: systemctl status показывает "failed"
Решение: проверь логи — journalctl -u telegram-bot -n 30
         Обычно: неправильный путь в ExecStart или забыл .env

2. ModuleNotFoundError на сервере

Проблема: бот не находит библиотеки (anthropic, telegram)
Причина: ExecStart указывает на системный Python, а не на venv
Решение: путь должен быть /home/botuser/my-telegram-bot/venv/bin/python3

3. Permission denied

Проблема: бот не может прочитать файл
Причина: файл принадлежит root, а бот работает от botuser
Решение: chown -R botuser:botuser /home/botuser/my-telegram-bot/

4. Потерял доступ к серверу после включения файрвола

Проблема: ufw enable без ufw allow OpenSSH
Решение: в панели управления Hetzner есть "Console" — аварийный доступ
         Через неё: ufw allow OpenSSH или ufw disable

Практика

Задание 1: Подключись к серверу

Подключись по SSH, выполни pwd, ls, python3 --version. Убедись, что всё работает.

Задание 2: Задеплой бота

Пройди весь чек-лист. В конце бот должен отвечать в Telegram, даже когда ты отключишься от SSH.

Задание 3: Проверь устойчивость

Перезапусти сервер:

reboot

Подожди минуту, потом напиши боту. Он должен ответить (systemd запустит его автоматически).


Задачки на закрепление

Задача 1: Зачем создавать отдельного пользователя botuser?

Ответ Безопасность. Root имеет неограниченный доступ ко всей системе. Если в боте окажется уязвимость и злоумышленник получит контроль — он получит доступ ко всему серверу. Пользователь `botuser` ограничен своей папкой — ущерб минимален.

Задача 2: Почему в ExecStart нужен Python из venv, а не системный?

Ответ Системный Python не знает про пакеты, установленные в venv (anthropic, python-telegram-bot). Если указать `/usr/bin/python3`, бот получит `ModuleNotFoundError`. Python из venv (`/home/botuser/my-telegram-bot/venv/bin/python3`) видит все пакеты, которые мы установили через `pip install`.

Задача 3: Что произойдёт, если не сделать ufw allow OpenSSH перед ufw enable?

Ответ Файрвол заблокирует ВСЕ входящие подключения, включая SSH. Ты потеряешь доступ к серверу через терминал. Решение: использовать аварийную консоль в панели управления Hetzner и выполнить `ufw allow OpenSSH` или `ufw disable`.

Задача 4: Как посмотреть, почему бот не запустился?

Ответ `journalctl -u telegram-bot -n 50` — покажет последние 50 строк логов сервиса. Там будет ошибка Python (ModuleNotFoundError, FileNotFoundError, неправильный токен и т.д.). Это первое, что нужно проверять при проблемах.

Глоссарий

Термин Что значит
Сервер Компьютер, который работает 24/7 и доступен через интернет
VPS Virtual Private Server — виртуальный сервер на хостинге
SSH Secure Shell — протокол для безопасного управления удалённым компьютером
IP-адрес Числовой адрес компьютера в сети (как адрес дома)
root Суперпользователь Linux с полным доступом ко всей системе
apt Менеджер пакетов Linux (как pip для Python, но для системы)
scp Secure Copy — копирование файлов через SSH
venv Виртуальное окружение Python (изолированные пакеты)
systemd Менеджер служб Linux. Управляет фоновыми процессами
Сервис (service) Программа, работающая в фоне под управлением systemd
systemctl Команда для управления сервисами (start, stop, restart, status)
journalctl Команда для чтения логов systemd
SIGHUP Сигнал "отключись", который процесс получает при закрытии SSH
chmod Команда для изменения прав доступа к файлу
ufw Uncomplicated Firewall — простой файрвол для Linux
SSH-ключ Пара файлов (приватный + публичный) для входа без пароля
Деплой Развёртывание — процесс переноса кода на сервер и запуска

Главное

Проблема:
  Бот на ноутбуке → закрыл терминал → бот умер

Решение:
  Сервер (VPS) + systemd → бот работает 24/7

Деплой в 4 шага:
  1. SSH → подключиться к серверу
  2. git clone → загрузить код
  3. venv + pip install → настроить окружение
  4. systemd → сделать бота службой

Управление:
  systemctl start/stop/restart telegram-bot
  journalctl -u telegram-bot -f  (логи)

Безопасность:
  ✓ Отдельный пользователь (не root)
  ✓ SSH-ключи (не пароли)
  ✓ Файрвол (ufw allow OpenSSH → ufw enable)
  ✓ chmod 600 .env (только владелец читает)

Что дальше?

Бот работает 24/7 на сервере, помнит разговоры в базе данных. В следующем уроке — платформы и OpenClaw: как устроены большие проекты с AI-агентами и как всё, что ты изучила, складывается в реальную систему.

← ПРЕДЫДУЩИЙ СЛЕДУЮЩИЙ →