Перейти к содержанию

Удалённый сервер

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

Пришло время настроить собственный удалённый сервер.

Вспомним, что можно купить, воткнуть в розетку и настроить https://www.raspberrypi.org/products/, и на первых порах этого будет достаточно, однако если дома выключат свет или отключат интернет, то будет неприятно. А ещё при большой нагрузке (например, если запущенным на сервере ботом начнет пользоваться большое количество людей) такое слабое железо не будет справляться и всё упадёт.

Хороший вариант — платить несколько баксов в месяц за аренду облачного сервера, который и работает бесперебойно, и масштабируется в случае больших нагрузок. Среди популярных решений можно выделить:

Digital Ocean (https://digitalocean.com)

Amazon Web Services (https://aws.amazon.com)

Google Cloud Platform (https://cloud.google.com)

Яндекс.Облако (https://cloud.yandex.ru)

У DO приятный интерфейс и очень крутые туториалы на русском языке по самым частым кейсам, AWS самый популярный, GCP немного сложный в настройке, а Я.Облако русскоязычный и там крутая служба поддержки, которая подробно отвечает на все вопросы в течение суток.

Выбрать можно любой. Каждый сервис предоставляет 2 месяца бесплатного пробного периода, чтобы принять решение о дальнейшем использовании. Можно попробовать все четыре по два месяца и потом определиться с выбором. Если не знаешь, с чего начать → начни с Digital Ocean, они норм :)

Если ты студент, то обязательно регистрируйся на GitHub Student Developer Pack: https://education.github.com/pack. Получишь бесплатный доступ на 10 месяцев на Digital Ocean + огромное количество других сервисов, которые дают бесплатный доступ на период обучения. Нужно будет отправить фотку студенческого билета с учебной почты и подождать несколько дней.

Регистрация и создание сервера сводится примерно к следующему: указываешь свою почту или телефон, подтверждаешь их, вводишь данные карты, у тебя списывается что-то вроде $1 и сразу же возвращается (это нужно, чтобы проверить платежеспособность). После успешной регистрации нужно создать виртуальную машину — так называется удаленный сервер (в DO это называется "дроплет"), при создании спросят всякие характеристики железа, выбирай минимальные, потом можно будет увеличить. Операционную систему можно выбрать любую, новичкам рекомендуется Ubuntu, её мы и будем использовать в курсе.

При создании виртуальной машины есть опция подключения по ssh-ключу, обязательно выбирай этот способ. Он заключается в том, что ты генерируешь у себя на компьютере две половинки ssh-ключа (публичный и приватный), одну часть закидываешь на сервер, а вторую держишь на своем компе и никому не показываешь. При подключении две половинки соединяются и ты получаешь доступ, таким образом на сервер может зайти только тот, у кого есть ключ. Рекомендуется сохранить этот ключ дополнительно где-нибудь в надеждом месте, например, на флешке.

Погугли "как сгенерировать ssh ключ", при генерировании обязательно указывай passphrase, это дополнительный пароль, он нужен для того, чтобы даже если кто-то украдёт вторую часть ключа, он не сможет попасть на сервер не зная пароль от этого ключа. После успешного создания виртуальной машины у тебя будет публичный адрес сервера (хост), пара логин-пароль или ssh-ключ для подключения (сохрани их в надеждом месте).

В общем, выбери один из облачных сервисов, зарегистрируйся и создай виртуальную машину (сервер). Если ты успешно смог подключиться к созданному серверу по ssh, как в первом уроке, значит всё окей и можно двигаться дальше. Если что-то пошло не так — пиши в чат!

Первоначальная настройка сервера

Первое, что нужно сделать — убедиться, что ты не сидишь под root'ом. root — это пользователь под номером 001, который обладает неограниченными правами, то есть может совершать на сервере любые действия. Некоторые сервисы делают это за тебя, некоторые нет. Набери команду whoami и убедись, что ты не рут. В противном случае нужно создать нового пользователя командой:

adduser dima

И наделить его правами суперпользователя:

usermod -aG sudo dima

Второе, что нужно сделать — отключить аутентификацию по паролю. Это делается очень просто — открываешь на редактирование файл /etc/ssh/sshd_config, находишь нужную строчку и выставляешь "no" напротив:

PasswordAuthentication no

Затем перезагружаешь ssh-демон командой:

sudo systemctl restart ssh

Демоном в Линукс называется любая постоянно запущенная программа, а systemctl — это утилита для работы с ними.

Теперь переподключившись как пользователь dima, ты всё так же сможешь выполнять команды как администратор, но важные команды придётся снабжать приставкой sudo, то есть если ты, например, захочешь добавить ещё одного пользователя, то вот так:

sudo adduser diana

Но есть один момент, так как мы отключили аутентификацию по паролю, пользователь diana никак не сможет попасть на сервер. Чтобы это исправить, надо попросить у Дианы её публичный ssh-ключ и скопировать его в файл ~/.ssh/authorized_keys. Теперь всё ок.

Теперь включаем файрволл, это базовое средство защиты сервера от несанкционированного доступа. Разрешим подключение к серверу только через ssh:

ufw allow OpenSSH
ufw enable

Теперь файрволл блокирует все подключения, кроме ssh. Отлично, минимальный уровень безопасности настроен.

Следующим шагом идёт обновление системы. В системе Ubuntu используется менеджер пакетов APT, это что-то вроде pip'а в Питоне. Перед тем, как устанавливать что-то через менеджер пакетов APT, нужно обновить его индекс (это локальная база данных, в которой хранятся версии всех пакетов), делается это командой:

sudo apt update

Затем непосредственно обновляем все установленные в системе пакеты командой:

sudo apt upgrade -y

Ключ -y означает yes, он нужен, чтобы на все возникающие при обновлении вопросы автоматически отвечалось yes.

Готово, теперь можно ставить на сервер python и git:

sudo apt install python3-pip python3-venv git -y

Эта команда установит третью версию python, модули pip и venv и git.

Запуск бота на сервере

Клонируй свой проект с ботом командой:

git clone ...

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

python3 -m venv venv
source venv/bin/activate
python -m pip install -r requirements.txt

И запусти бота. Всё должно работать.

Остался ещё один шаг — нужно сделать так, чтобы бот автоматически стартовал при перезапуске сервера и автоматически поднимался в случае падения. В этом нам поможет systemd — системный менеджер, он управляет всеми процессами.

Поручим systemd следить за нашим ботом, создадим сервис (так называются запущенные программы, за которыми надо следить).

Создай файл bot.service в директории /etc/systemd/system:

[Unit]
Description=My telegram bot
After=network.target

[Service]
User=root
ExecStart=/usr/bin/python3 /home/dima/mybotrepo/bot.py
RestartSec=10
Restart=always

[Install]
WantedBy=multi-user.target

Первые две команды — это просто описание сервиса и указание запускать его только после того, как будут запущено подключение к сети.

Далее User — от чьего имени запускать сервис, измени на своё текущее имя пользователя.

ExecStart — путь до интерпретатора питона (можно узнать его командой which python) и путь до файла, запускающего бота.

Две команды про перезапуск:

RestartSec таймаут перезапуска и Restart — политика перезапуска. В нашем случае будет перезапускаться всегда, каждые 10 секунд.

Последняя строчка про то, к какому классу отнести этот юнит, для группировки юнитов по классам, не бери в голову.

И, наконец, выполни в терминале:

systemctl daemon-reload
systemctl enable bot
systemctl start bot
systemctl status bot

Здесь мы перезапустили список демонов, сказали что сервис bot должен работать постоянно, запустили его и вывели статус. Если статус active, значит всё окей — systemd теперь следит за ним и будет поддерживать постоянную работу!

Теперь некоторые полезные сервисы.

Полезные сервисы

Uptime Robot

Uptime Robot — замечательный сервис, который будет тестировать твой сервис из вне: пинговать его каждые 5 минут, и в случае, если не получит ответа, отправит тебе сообщение на почту или в телеграм. Для этого нужно подтвердить почту или нажать /start их боту. Там есть удобная статистика и всё это бесплатно!

Зайди на https://uptimerobot.com и зарегистрируйся. После подтверждения почты ты сможешь залогиниться и увидишь зеленую кнопку Add New Monitor — нажимай. Придумай монитору имя, например "Сервер Digital Ocean" (оно будет отображаться в списке мониторов слева на дашборде), укажи хост, справа выбери куда тебя оповещать о сбоях в работе:

Нажми Save Changes. Готово, теперь Uptime Robot будет мониторить твой сервер и рисовать такую красивую статистику:

Теперь проверь, что мониторинг работает — зайди в настройки виртуальной машины (дроплета) и потуши сервер, в зависимости от того, какой сервис ты используешь, там будет что-то похожее на "остановить" или "stop", в общем найдёшь. Если в течение пяти минут на почту и в Телеграм пришло уведомление о том, что монитор IS DOWN, значит всё работает. Если не пришло, то нужно пройти в Settings и подтвердить почту/активировать бота в телеграме, чтобы он мог отправлять уведомления. Не забудь запустить сервер обратно. :)

Кстати, совет на будущее — виртуальную машину (дроплет) можно останавливать на время, а потом снова запускать. Лучше всего это делать, когда сервер не используется, позволяет сэкономить деньги.

Sentry

Sentry — крутая штука, которая тоже мониторит, но не сервер, а ошибки в работе твоего запущенного приложения (например, бота) и тоже присылает уведомления/рисует красивые графики.

Чтобы подключить Сентри, сначала зарегистрируйся на https://sentry.io/signup/, выбери в приветственном окне Python, появится инструкция по подключению его в проект. Там всё доходчиво описано — нужно установить пакет через pip, подключить его в проект, добавив пару строк кода с токеном и добавить в свой код какую-нибудь ошибку, например операцию деления на ноль, после чего вызвать этот код и получить ошибку в свой дашборд. Можешь выполнить это локально, на своем компьютере, чтобы проверить, а затем запушь код на GitHub и подтяни изменения на сервер, выполнив там команду git pull. Затем перезапусти бота на сервере. Не забудь обновить файл .env, внеся туда токен Сентри.

Что дальше?

До встречи в следующем году)