Discord Bot Hosting: Keep Your Bot Online with systemd or Docker

To host a Discord bot 24/7, run it on an always-on Linux VPS as a managed service, either a systemd unit or a Docker container with a restart policy, so it starts on boot and comes back after a crash. Most bots built with discord.js or discord.py keep a WebSocket connection open to Discord's gateway, which is why they need a server that never sleeps. Keep the token in an environment file, enable only the intents you need, and add logging so you know when something breaks.
Gateway bots vs an interactions endpoint
Discord offers two ways to receive events, and the choice affects hosting.
Gateway bots open an outbound WebSocket connection to Discord and receive events in real time: messages, members joining, reactions, voice state changes and slash commands. discord.js and discord.py work this way by default. The process must stay running, but because the connection is outbound you don't need an open inbound port or a domain name.
An interactions endpoint is an HTTPS URL you give Discord instead. Discord sends slash commands, button clicks and other interactions to it as POST requests. Your endpoint must verify each request's Ed25519 signature (the
X-Signature-Ed25519andX-Signature-Timestampheaders, checked against your application's public key) and send an initial response within 3 seconds, or defer and follow up later. You don't receive gateway events such as ordinary messages this way.
If your bot reads messages, reacts to members joining, plays audio or tracks presence, you need the gateway, and a VPS is its natural home. If it only answers slash commands, an interactions endpoint is an option, though it still needs a reliable HTTPS server.
How much server a Discord bot needs
A typical moderation, utility or community bot in a handful of servers uses little CPU and a modest amount of RAM; the runtime and the library's cache are the main consumers. Requirements grow with:
Number of servers and members: libraries cache guilds, channels, members and messages in memory. Limiting caches, such as message cache size or member caching, keeps RAM in check.
Music and voice: audio processing with FFmpeg is far heavier on CPU than text commands.
AI features: calling a model API is light; running a model locally is not.
A database: PostgreSQL or SQLite for settings, levels, tickets or logs.
For most single bots, 1 vCPU and 2 GB of RAM is plenty. Watch memory as the bot joins more servers. If you are weighing a VPS against serverless or managed options, our comparison of where to host an AI agent applies to bots too.
Step 1: Create the bot and choose intents
In the Discord Developer Portal, create an application, add a bot user and copy its token. Then decide on gateway intents, which control which events Discord sends you:
Standard intents such as
GuildsandGuildMessagesare available to every bot.Privileged intents (Message Content, Server Members and Presence) must be switched on in the Developer Portal before your code can request them. Bots in 100 or more servers must be verified, and verified bots need Discord's approval to use privileged intents.
Request only what you use. A bot built on slash commands doesn't need the Message Content intent, because command options arrive inside the interaction itself.
// discord.js
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent] // privileged: enable it in the portal
});
client.login(process.env.DISCORD_TOKEN);# discord.py
import os, discord
intents = discord.Intents.default()
intents.message_content = True # privileged: enable it in the portal
client = discord.Client(intents=intents)
client.run(os.environ["DISCORD_TOKEN"])Step 2: Prepare the server
On a fresh Ubuntu or Debian VPS, update packages, create a dedicated system user for the bot, and lock down SSH with keys and a firewall; our guide to securing a Linux VPS with SSH keys, UFW and Fail2ban walks through it. A gateway bot needs no inbound ports, so the firewall can allow SSH only.
sudo apt update && sudo apt install -y python3-venv
sudo adduser --system --group --home /opt/discord-bot bot
# copy your code into /opt/discord-bot, then for discord.py:
sudo -u bot python3 -m venv /opt/discord-bot/venv
sudo -u bot /opt/discord-bot/venv/bin/pip install -r /opt/discord-bot/requirements.txtStep 3: Keep the token secret
The token is full control of your bot: anyone who has it can act as the bot in every server it belongs to.
Store it in an environment file readable only by the bot user, for example
/opt/discord-bot/.envcontainingDISCORD_TOKEN=..., with permissions600.Never commit it to Git; add
.envto.gitignore.If it leaks, reset it in the Developer Portal straight away and update the file.
Step 4: Run it as a service
Option A: systemd
[Unit]
Description=Discord bot
Wants=network-online.target
After=network-online.target
[Service]
User=bot
WorkingDirectory=/opt/discord-bot
EnvironmentFile=/opt/discord-bot/.env
ExecStart=/opt/discord-bot/venv/bin/python bot.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.targetSave it as /etc/systemd/system/discord-bot.service, then run sudo systemctl daemon-reload and sudo systemctl enable --now discord-bot. For a discord.js bot, point ExecStart at your Node.js binary and entry file instead.
Option B: Docker Compose
services:
bot:
build: .
env_file: .env
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"Docker suits bots with several parts (the bot, a database, a web dashboard) and makes moving to another server simple. The logging options stop container logs from slowly filling the disk.
Reconnects and restarts
Gateway connections drop from time to time: network blips, Discord asking clients to reconnect, or an invalidated session. discord.js and discord.py reconnect and resume sessions on their own, so don't write your own reconnect loop. What the library can't fix is your process crashing on an unhandled exception, and that is what Restart=always or restart: unless-stopped is for. Keep a restart delay such as RestartSec so a crash loop doesn't hammer Discord with logins; new gateway sessions are rate limited.
Logging and monitoring
With systemd, follow logs with
journalctl -u discord-bot -f; with Docker, usedocker compose logs -f bot.Log errors with enough context (command name, guild ID) to reproduce them, but never log the token or users' private messages.
Add a health signal: a periodic heartbeat to an uptime monitor, or a command that reports gateway latency.
Watch memory over weeks. A slow, steady climb usually means an unbounded cache or a leak.
Sharding for large bots
One gateway connection can only serve so many servers. Discord requires sharding once a bot reaches 2,500 servers, and it is sensible to plan for it before then. Each shard is a separate connection handling a subset of guilds. discord.js provides a ShardingManager that runs shards as separate processes, and discord.py offers AutoShardedClient. At that size you will usually move from one small VPS to a larger server or several servers sharing a database.
Updating the bot safely
Pin library versions in
package.jsonorrequirements.txt, and read the changelog before major upgrades; both discord.js and discord.py have shipped breaking changes in major versions.Test with a separate development bot in a private test server before restarting the production one.
Deploy with a short script: pull the code, install dependencies, restart the service, check the logs.
Keep the operating system patched; unattended security updates are a sensible default on Ubuntu and Debian.
If you run bots on other platforms too, the patterns carry over: see hosting a Telegram bot 24/7 on a VPS, and for webhook-based bots with conversation storage, WhatsApp bot hosting.
Frequently asked questions
Can I host a Discord bot for free?
You can run it on your own computer while it is switched on. Free hosting tiers often sleep when idle, which drops the gateway connection, so they rarely give true 24/7 uptime.
Does a Discord bot need open ports or a domain?
A gateway bot doesn't; it connects outbound to Discord. An interactions endpoint does, because Discord has to reach it over HTTPS.
Why can't my bot read message text?
The Message Content intent is privileged. Enable it in the Developer Portal and request it in your code, or switch to slash commands, which don't need it.
How much RAM does a Discord bot need?
Small bots run comfortably within 2 GB. Large member caches, music playback and local AI models are what push requirements up.
Hosting your Discord bot on IM HOST
AI Agent Hosting servers run around the clock with Docker, Node.js, Python and PostgreSQL with pgvector pre-installed, full root access and free daily backups, which suits bots with AI features, a database or several services. If you prefer a plain server, a Linux VPS gives you an unmanaged KVM machine on NVMe storage with full root access and a dedicated IPv4, which is all a gateway bot needs.
More from our blog
Discover more practical guides and product insights from the IM Host team.
View all articles