Discord.js бот: установка на VPS
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:
- Нажмите New Application, дайте имя — это будет имя бота в Discord.
- На вкладке General Information скопируйте Application ID — это ваш
CLIENT_ID. - Перейдите на вкладку Bot, нажмите Reset Token (или Copy при первом создании) и сохраните токен — Discord показывает его один раз, при повторном заходе только сброс.
- На той же вкладке включите нужные Privileged Gateway Intents. Для минимального бота со слэш-командами специальные intents (Message Content, Presence, Server Members) обычно не нужны — они требуются, только если бот читает содержимое обычных сообщений или следит за списком участников.
- Перейдите в OAuth2 → URL Generator, отметьте scope
botиapplications.commands, ниже выберите права (permissions) — для теста достаточноSend MessagesиUse Slash Commands. - Скопируйте сгенерированную ссылку, откройте её в браузере и добавьте бота на свой сервер (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.