MAATRIX / Блог / Discord.js бот: установка на VPS

Discord.js бот: установка на VPS

Discord.js бот: установка на VPS

MAATRIX

Discord-бот, который работает только пока открыт ноутбук — это не бот, а демо-версия. Если сервер выключен или провайдер вырезал доступ к Discord API из-за санкций, бот молчит именно тогда, когда он нужен сообществу. Ниже — рабочий маршрут: с нуля от чистой Ubuntu до бота на discord.js, который переживает перезагрузки и падения через pm2.

Что понадобится и подготовка сервера

Понадобится VPS с публичным IP и Node.js на борту, аккаунт Discord и 20-30 минут. Discord API доступен без специфических блокировок для большинства локаций, но если сервер стоит в России, стабильнее брать площадку за пределами страны — меньше шансов на разрывы соединения к discord.com и gateway.discord.gg.

Первым делом — базовая гигиена сервера на Ubuntu 22.04/24.04:

apt update && apt upgrade -y
adduser botuser
usermod -aG sudo botuser
su - botuser

Заводить бота под root — плохая идея: если в коде окажется уязвимость или зависимость подложит вредоносный пакет, ущерб ограничится правами обычного пользователя, а не всей системы. Дальше вся установка — от имени botuser.

Установка Node.js на VPS

discord.js требует довольно свежий Node.js — актуальная мажорная версия библиотеки (v14) работает начиная с Node 16.11, но на новый проект в 2026 году разумно ставить Node 20 LTS: он получает обновления безопасности дольше и лучше поддержан пакетами экосистемы. Ставим через NodeSource, а не через apt напрямую — в стандартных репозиториях Ubuntu версия обычно устаревшая:

curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node -v
npm -v

Если предпочитаете управлять несколькими версиями Node на одном сервере (например, для разных ботов с разными зависимостями), удобнее nvm:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm install 20
nvm use 20

Оба варианта рабочие, разница в удобстве обслуживания: nvm проще переключать версии, пакетный менеджер — проще обновлять системными средствами вместе с остальным сервером.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Создание проекта и установка discord.js

Создаём директорию под бота и инициализируем проект:

mkdir ~/discord-bot && cd ~/discord-bot
npm init -y
npm install discord.js dotenv
npm install @discordjs/rest discord-api-types

discord.js — основная библиотека для работы с Gateway и REST API Discord. dotenv нужен, чтобы токен бота не лежал в коде открытым текстом, а читался из файла .env, который не попадёт в git. @discordjs/rest и discord-api-types понадобятся отдельно для регистрации слэш-команд — это делается через прямой REST-запрос, а не через основной клиент.

Создайте .env в корне проекта:

DISCORD_TOKEN=вставьте_сюда_токен_бота
CLIENT_ID=вставьте_сюда_application_id
GUILD_ID=вставьте_сюда_id_тестового_сервера

И сразу добавьте .env в .gitignore, если планируете держать код в репозитории — утечка токена означает, что кто угодно сможет управлять вашим ботом от вашего имени.

Создание приложения в Discord Developer Portal

Токен и Application ID берутся не из кода, а из Discord Developer Portal:

  1. Нажмите New Application, дайте имя — это будет имя бота в Discord.
  2. На вкладке General Information скопируйте Application ID — это ваш CLIENT_ID.
  3. Перейдите на вкладку Bot, нажмите Reset Token (или Copy при первом создании) и сохраните токен — Discord показывает его один раз, при повторном заходе только сброс.
  4. На той же вкладке включите нужные Privileged Gateway Intents. Для минимального бота со слэш-командами специальные intents (Message Content, Presence, Server Members) обычно не нужны — они требуются, только если бот читает содержимое обычных сообщений или следит за списком участников.
  5. Перейдите в OAuth2 → URL Generator, отметьте scope bot и applications.commands, ниже выберите права (permissions) — для теста достаточно Send Messages и Use Slash Commands.
  6. Скопируйте сгенерированную ссылку, откройте её в браузере и добавьте бота на свой сервер (Guild). ID этого сервера, доступный через Server Settings → Widget или в режиме разработчика Discord (правый клик по серверу → Copy Server ID), — это ваш GUILD_ID.

Регистрация слэш-команд на конкретный сервер (GUILD_ID) применяется мгновенно и подходит для разработки. Глобальная регистрация (без GUILD_ID) видна на всех серверах, где стоит бот, но обновляется до часа — на проде так и делают, на этапе отладки — только через тестовый сервер.

Минимальный рабочий бот со слэш-командой

Файл deploy-commands.js — регистрирует команду /ping на тестовом сервере:

require('dotenv').config();
const { REST, Routes } = require('discord.js');

const commands = [
  {
    name: 'ping',
    description: 'Проверка, что бот жив',
  },
];

const rest = new REST().setToken(process.env.DISCORD_TOKEN);

(async () => {
  try {
    await rest.put(
      Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
      { body: commands },
    );
    console.log('Слэш-команды зарегистрированы');
  } catch (error) {
    console.error(error);
  }
})();

Файл index.js — сам бот:

require('dotenv').config();
const { Client, GatewayIntentBits, Events } = require('discord.js');

const client = new Client({
  intents: [GatewayIntentBits.Guilds],
});

client.once(Events.ClientReady, (readyClient) => {
  console.log(`Бот запущен как ${readyClient.user.tag}`);
});

client.on(Events.InteractionCreate, async (interaction) => {
  if (!interaction.isChatInputCommand()) return;

  if (interaction.commandName === 'ping') {
    await interaction.reply('Понг! Бот на связи.');
  }
});

client.login(process.env.DISCORD_TOKEN);

Обратите внимание на intents: [GatewayIntentBits.Guilds] — это минимальный набор, достаточный для получения слэш-команд. Каждый лишний intent — это дополнительные данные, которые Discord присылает боту, и дополнительная нагрузка на память процесса; включайте только то, что реально используете.

Запуск:

node deploy-commands.js
node index.js

Если в консоли появилось Бот запущен как ИмяБота#0000 и команда /ping отвечает на сервере — минимальный бот работает. Дальше — сделать так, чтобы он не останавливался при закрытии SSH-сессии и перезагрузке сервера.

Автозапуск и работа 24/7 через pm2

Node.js-процесс, запущенный через node index.js, умирает вместе с SSH-сессией. Для продакшена нужен process manager — pm2 берёт на себя автоперезапуск при падении, автозапуск при перезагрузке сервера и ротацию логов.

sudo npm install -g pm2
cd ~/discord-bot
pm2 start index.js --name discord-bot

Настройка автозапуска при перезагрузке сервера:

pm2 startup

Команда выведет строку вида sudo env PATH=$PATH pm2 startup systemd -u botuser --hp /home/botuser — её нужно скопировать и выполнить отдельно. После этого:

pm2 save

Эта команда фиксирует текущий список процессов pm2, чтобы после перезагрузки он поднял именно этот набор ботов. Основные команды на каждый день:

КомандаЧто делает
pm2 listСписок запущенных процессов, статус, память, CPU
pm2 logs discord-botЛоги бота в реальном времени
pm2 restart discord-botПерезапуск после изменения кода
pm2 stop discord-botОстановка без удаления из списка
pm2 monitМониторинг CPU/памяти в реальном времени

pm2 автоматически перезапустит бота при падении (например, необработанное исключение в коде), но если бот падает раз в минуту — это симптом бага, а не повод радоваться автоперезапуску. Смотрите pm2 logs при первых признаках нестабильности. Для распределения ресурсов, если на сервере крутится несколько ботов, полезно прикинуть заранее, сколько ресурсов реально нужно VPS под ботов — логика расчёта для Discord-бота почти идентична телеграм-боту: минимальный процесс на Node.js спокойно живёт на 512 МБ — 1 ГБ RAM, если не грузит в память тяжёлые модели или большие кэши.

Для деплоя новой версии кода: git pull (или scp файлов), затем pm2 restart discord-bot. Никакой пересборки контейнеров, никакого простоя дольше пары секунд.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать VPS

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Discord.js версии 13 или 14 — что ставить?

На новый проект в 2026 году ставьте актуальную версию из npm (npm install discord.js берёт последнюю стабильную) — v14 давно основная, v13 в архиве и не получает обновлений безопасности. Перед миграцией старого бота стоит свериться с changelog: между мажорными версиями меняется структура intents и часть API.

Почему бот не отвечает на слэш-команду, хотя виден онлайн?

Чаще всего команда не зарегистрирована — проверьте, что deploy-commands.js отработал без ошибок и CLIENT_ID/GUILD_ID в .env верные. Второй частый случай — бот не добавлен в Discord с scope applications.commands, а только с bot; тогда слэш-команды физически не появятся у него в списке на сервере.

Нужен ли Message Content Intent?

Только если бот читает текст обычных сообщений (не через слэш-команды) — например, реагирует на ключевые слова в чате. Для этого intent с недавних пор нужна отдельная верификация приложения в Discord Developer Portal, если бот стоит на 100+ серверах; для личного бота на своём сервере включение проходит без дополнительной верификации.

Что делать, если процесс падает с ошибкой ECONNRESET или таймаутами к gateway.discord.gg?

Обычно это сетевые проблемы на стороне провайдера VPS, а не баг в коде — из некоторых регионов доступ к инфраструктуре Discord менее стабилен. Если разрывы регулярные, стоит сменить локацию сервера — площадка ближе к дата-центрам Discord (обычно US/EU) даёт заметно более стабильное соединение, чем сервер в РФ.

Можно ли держать несколько ботов на одном VPS?

Да, pm2 спокойно управляет несколькими процессами одновременно — каждому свой --name и своя папка проекта. Ограничение практическое: суммарная память и CPU всех процессов должны укладываться в ресурсы сервера, поэтому для трёх-пяти ботов лучше сразу брать план с запасом, а не самый минимальный.

Как обновить бота без даунтайма?

Для одного бота короткий рестарт (pm2 restart) — это доли секунды простоя, для Discord-сообщества это некритично. Если нужен честный zero-downtime, разворачивайте два инстанса за очередью команд или используйте pm2 reload вместо restart — он поднимает новый процесс до того, как остановит старый, но это требует, чтобы бот поддерживал graceful shutdown.