This guide shows how to create an application and a bot in the Discord Developer Portal, protect its token, invite it to a community server, then host it 24/7 on a Linux VPS (systemd, pm2 or Docker). Allow 30 to 45 minutes; an entry-level VPS is enough for a small bot.
Step-by-step installation
Enable two-factor authentication on your Discord account and install a current LTS version of Node.js (or Python) on your machine.
Create an application at discord.com/developers/applications (New Application).
Bot tab: generate the token (Reset Token) and copy it once into a password manager or a .env file.
Enable only the Privileged Gateway Intents you actually use (Presence, Server Members, Message Content).
Generate the invite link (bot + applications.commands scopes, minimal permissions) with the “Bot invite link” tool.
Open the link, pick your server (Manage Server permission required) and authorize.
Write a minimal bot (discord.js) and test it locally with the token in .env.
Prepare a Linux VPS: non-root user, firewall, Node.js (see the “Prepare a VPS” guide).
Deploy the code, put the token in a .env file (chmod 600) and run the bot with systemd, pm2 or Docker.
Configure the community server: roles, channels, permissions, webhooks and moderation.
Prerequisites
You need a Discord account (with 2FA), a server you own or administer, and Node.js LTS (or Python): check the minimum version required by the discord.js release you install. For hosting: a Linux VPS (1 vCPU and 512 MB to 1 GB RAM are usually enough for a small bot, adjust to your code). Never share the bot token: it gives full control of the bot.
Create the application and the bot
- discord.com/developers/applications → New Application → name → Create.
- General Information: copy the Application ID (the public client_id).
- Bot → Reset Token → copy the token (shown only once).
- If the token leaks (public Git repo, screenshot…), immediately click Reset Token.
Protect the token (.env)
Never put the token in the code. Use a .env file excluded from Git and readable only by your user. Example (dummy value):
echo 'DISCORD_TOKEN=ChangeMe!' > .env
chmod 600 .env
echo '.env' >> .gitignorePrivileged Intents
- Server Members Intent: member join/leave events and the full member list.
- Message Content Intent: reading message text (not needed if you only use slash commands).
- Presence Intent: member presence statuses.
- Beyond a certain number of servers (100 per Discord's policy at the time of writing), these intents require bot verification: check the current policy.
Invite the bot
The invite link looks like this (dummy client_id, permissions = 3072: view and write in channels). Compute the integer with the permissions calculator and assemble the link with the dedicated tool:
https://discord.com/oauth2/authorize?client_id=123456789012345678&scope=bot%20applications.commands&permissions=3072Minimal bot (discord.js)
Install: npm init -y && npm install discord.js dotenv. File index.js (see discordjs.guide for the up-to-date API):
require('dotenv').config();
const { Client, Events, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (c) => console.log(`Logged in as ${c.user.tag}`));
client.login(process.env.DISCORD_TOKEN);Host with systemd
File /etc/systemd/system/discord-bot.service (adapt User and paths; check node's path with “which node”). Then: sudo systemctl daemon-reload && sudo systemctl enable --now discord-bot; logs: journalctl -u discord-bot -f.
[Unit]
Description=Discord bot
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=botuser
WorkingDirectory=/home/botuser/bot
EnvironmentFile=/home/botuser/bot/.env
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetHost with pm2
pm2 restarts the process if it crashes. The “pm2 startup” command prints a sudo command to run so pm2 starts at boot.
sudo npm install -g pm2
pm2 start index.js --name discord-bot
pm2 save
pm2 startup
pm2 logs discord-botHost with Docker
Dockerfile below (match the Node version to the one discord.js requires). Build and run with the token passed through an env file: docker build -t discord-bot . && docker run -d --restart unless-stopped --env-file .env --name discord-bot discord-bot
FROM node:lts-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
CMD ["node", "index.js"]Set up the community server
- Roles: create roles by function (admin, moderator, member) and grant minimal permissions; the bot's role must sit above the roles it manages.
- Channels: categories (welcome, rules, general, support, voice) and permissions per category rather than per channel.
- Webhooks: to post your game servers' status, build the embed with the “Webhook embed builder” tool.
- Moderation: verification level, AutoMod, audit log; enable the 2FA requirement for moderators in server settings.
- Visibility: list your game server on game-rank.com/jeux to get discovered.
Troubleshooting
- “TokenInvalid” / “An invalid token was provided”: wrong token, stray space, or token was reset. Re-copy it via Reset Token.
- “Used disallowed intents”: enable the matching privileged intent in the Bot tab, or remove it from the code.
- “Missing Access” / “Missing Permissions”: the bot lacks permission in that channel or its role is too low in the hierarchy.
- Slash commands don't appear: the applications.commands scope was missing from the invite, or commands aren't registered (deployment); re-invite the bot with the right link.
- The bot disconnects on the VPS: read the logs (journalctl -u discord-bot -f), check available memory and that Restart=on-failure is set.
Frequently asked questions
- Is a Discord bot free?
- Creating a bot in the Developer Portal is free. Only hosting (a VPS or an always-on machine) may cost a few euros per month.
- What if my token leaked?
- Immediately click Reset Token in the Bot tab, update your .env file, restart the bot and check the server's audit log.
- systemd, pm2 or Docker?
- systemd is lightest and built into Linux; pm2 is handy if you run several Node.js processes; Docker isolates the environment and makes deployment reproducible. All three restart the bot after a crash.
- Do I need an open port to host a bot?
- No: the bot opens an outgoing connection to Discord itself. Only the SSH port needs to stay reachable for administration (unless you expose a web server).
