How to Host a Discord Bot 24/7 on a VPS (Python & Node.js Guide)
Running a Discord bot on your own computer or a free hosting platform is fine for testing, but it falls apart the moment you need reliability. Free tiers sleep after inactivity, your PC restarts for updates at 3 AM, and your router occasionally drops its connection. A VPS solves every one of these problems by giving your bot a dedicated, always-on Linux server in a data centre with redundant power and network connectivity. This guide walks you through the entire process of hosting a Discord bot 24/7 on a VPS, with complete code examples for both Python and Node.js.
A VPS is the best way to keep a Discord bot online 24/7. You need very little power (1 vCPU, 1-2 GB RAM). Set up Ubuntu, install Python or Node.js, upload your bot code, and use systemd or pm2 to keep it running through crashes and reboots. BearHost VPS plans start at $4.49/mo with full root access.
Why You Need a VPS for Your Discord Bot
There are three common approaches to running a Discord bot: your own PC, a free hosting platform, or a VPS. Each has trade-offs, but only a VPS delivers true 24/7 uptime with the control you need.
Running a bot on your personal computer means it goes offline every time you restart, lose power, or your internet drops. Your computer also needs to stay awake around the clock, which increases electricity costs and hardware wear. If you share the machine with other tasks, resource contention can cause your bot to lag or crash during peak usage.
Free hosting platforms like Replit, Glitch, or Railway free tiers are popular for prototyping, but they introduce serious limitations for production bots. Most free tiers spin down your process after 15 to 30 minutes of inactivity. When a user sends a command to your bot, it first has to cold-start, which can take 10 to 30 seconds. Some platforms impose bandwidth caps, restrict outbound connections, or limit execution time. You also have no control over the runtime environment, installed packages, or system-level configuration.
A VPS gives you a dedicated virtual server in a data centre with enterprise-grade power, cooling, and network infrastructure. Your bot runs on its own isolated Linux instance with full root access. You control the operating system, installed software, firewall rules, and process management. Data centres maintain 99.9% or higher uptime with redundant power supplies, backup generators, and multiple network providers. The result is a bot that stays online through power cuts, ISP outages, and hardware failures that would take down a home setup.
For most Discord bots, even those serving thousands of users, the hardware requirements are minimal. A single vCPU and 1 to 2 GB of RAM handles a typical bot with ease, which means VPS hosting is surprisingly affordable.
Choosing the Right VPS Specs for a Discord Bot
Discord bots are lightweight applications. They maintain a WebSocket connection to the Discord gateway, listen for events, and respond with API calls. Unless your bot performs heavy computation like image processing, machine learning inference, or serving a web dashboard alongside the bot process, you need very little horsepower.
For a single bot serving up to a few thousand members, 1 vCPU and 1 GB of RAM is sufficient. If your bot handles music streaming, processes images, or runs a database alongside it, step up to 2 GB of RAM. Bots that serve multiple large servers simultaneously or run resource-intensive background tasks benefit from 2 vCPUs and 4 GB of RAM, but this is the exception rather than the rule.
Storage requirements are equally modest. Your bot code, dependencies, and logs will typically consume under 1 GB of disk space. A 20 GB SSD is more than enough unless you are storing large amounts of user data in a local database.
Get a BearHost VPS for your Discord bot — from $4.49/mo with full root access at BearHost VPS Hosting. BearHost VPS plans include NVMe SSD storage, unmetered bandwidth, and full root access, which is everything a Discord bot needs to run reliably around the clock. The 1 vCPU and 2 GB RAM plan is the sweet spot for most bots.
Step-by-Step: Setting Up an Ubuntu VPS for Your Discord Bot
This section assumes you have just provisioned a fresh Ubuntu 22.04 or 24.04 VPS. You will connect via SSH, secure the server, and install the runtime your bot needs.
Start by connecting to your VPS using the IP address and root credentials from your hosting provider. Open a terminal on your local machine and run the following command, replacing the IP address with your own.
Connect to Your VPS via SSH
ssh root@your-server-ip
Update the System and Install Essential Packages
After connecting, update the package list and upgrade all installed packages to their latest versions. This ensures you have the latest security patches and bug fixes.
apt update && apt upgrade -y apt install -y git curl wget unzip htop
Create a Non-Root User for Your Bot
Running your bot as root is a security risk. If your bot has a vulnerability, an attacker gains full server access. Create a dedicated user with sudo privileges instead.
adduser botuser usermod -aG sudo botuser su - botuser
Configure the Firewall
Ubuntu includes UFW (Uncomplicated Firewall). Enable it and allow SSH so you do not lock yourself out.
sudo ufw allow OpenSSH sudo ufw enable sudo ufw status
Install Python (for discord.py Bots)
Ubuntu 22.04 and 24.04 ship with Python 3 pre-installed, but you need pip and venv for managing dependencies.
sudo apt install -y python3 python3-pip python3-venv python3 --version
Install Node.js (for discord.js Bots)
Use the NodeSource repository to install the latest LTS version of Node.js. This gives you a recent, stable release rather than the older version in the default Ubuntu repositories.
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs node --version npm --version
Deploying a Python Discord Bot (discord.py)
With the server configured, it is time to deploy your bot. This section covers uploading your code, setting up a virtual environment, installing dependencies, and running the bot.
First, create a directory for your bot and set up a Python virtual environment. Virtual environments isolate your bot dependencies from the system Python installation, preventing conflicts with other applications.
Create the Project Directory and Virtual Environment
mkdir -p ~/discord-bot && cd ~/discord-bot python3 -m venv venv source venv/bin/activate pip install discord.py python-dotenv
Create Your Python Bot File
Here is a complete, production-ready Python Discord bot template. It uses environment variables for the token (never hard-code secrets), includes error handling, and demonstrates basic command and event handling.
# bot.py import os import discord from discord.ext import commands from dotenv import load_dotenv load_dotenv() TOKEN = os.getenv("DISCORD_TOKEN") intents = discord.Intents.default() intents.message_content = True bot = commands.Bot(command_prefix="!", intents=intents) @bot.event async def on_ready(): print(f"{bot.user} is online and ready!") print(f"Connected to {len(bot.guilds)} server(s)") @bot.command(name="ping") async def ping(ctx): latency = round(bot.latency * 1000) await ctx.send(f"Pong! Latency: {latency}ms") @bot.command(name="serverinfo") async def server_info(ctx): guild = ctx.guild embed = discord.Embed( title=guild.name, description=f"Members: {guild.member_count}", color=discord.Color.blue() ) embed.add_field(name="Created", value=guild.created_at.strftime("%B %d, %Y")) embed.add_field(name="Owner", value=guild.owner) await ctx.send(embed=embed) @bot.event async def on_command_error(ctx, error): if isinstance(error, commands.CommandNotFound): return elif isinstance(error, commands.MissingPermissions): await ctx.send("You do not have permission to use this command.") else: await ctx.send("An error occurred. Please try again.") print(f"Error: {error}") bot.run(TOKEN)
Create the Environment File
Store your bot token in a .env file. Never commit this file to version control. Replace the placeholder with your actual token from the Discord Developer Portal.
# .env DISCORD_TOKEN=your-bot-token-here
Upload Your Code to the VPS
If your bot code is in a Git repository, clone it directly onto the server. This is the recommended approach because it makes updates as simple as running git pull.
cd ~ git clone https://github.com/yourusername/discord-bot.git cd discord-bot source venv/bin/activate pip install -r requirements.txt
Alternative: Upload with SCP
If your code is not in a Git repository, use SCP to upload files from your local machine. Run this command from your local terminal, not from the VPS.
scp -r ./discord-bot botuser@your-server-ip:~/discord-bot
Test the Python Bot Manually
Before setting up automatic process management, run the bot manually to confirm everything works.
cd ~/discord-bot source venv/bin/activate python3 bot.py
You should see your bot come online in Discord. Test a command like !ping to verify it responds. Press Ctrl+C to stop the bot once you have confirmed it works. The next step is to set up a process manager so it runs automatically in the background.
Deploying a Node.js Discord Bot (discord.js)
The process for a Node.js bot is similar. Create a project directory, initialise a Node.js project, install dependencies, and write your bot code.
Set Up the Node.js Project
mkdir -p ~/discord-bot && cd ~/discord-bot npm init -y npm install discord.js dotenv
Create Your Node.js Bot File
Here is a complete, production-ready Node.js Discord bot template using discord.js v14. It follows the same best practices as the Python version: environment variables for secrets, error handling, and clean event-driven architecture.
// bot.js require("dotenv").config(); const { Client, GatewayIntentBits, EmbedBuilder } = require("discord.js"); const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, ], }); const PREFIX = "!"; client.on("ready", () => { console.log(`${client.user.tag} is online and ready!`); console.log(`Connected to ${client.guilds.cache.size} server(s)`); }); client.on("messageCreate", async (message) => { if (message.author.bot) return; if (!message.content.startsWith(PREFIX)) return; const args = message.content.slice(PREFIX.length).trim().split(/\s+/); const command = args.shift().toLowerCase(); if (command === "ping") { const latency = Math.round(client.ws.ping); await message.reply(`Pong! Latency: ${latency}ms`); } if (command === "serverinfo") { const guild = message.guild; const embed = new EmbedBuilder() .setTitle(guild.name) .setDescription(`Members: ${guild.memberCount}`) .setColor(0x5865f2) .addFields( { name: "Created", value: guild.createdAt.toDateString(), inline: true }, { name: "Owner", value: `<@${guild.ownerId}>`, inline: true } ); await message.reply({ embeds: [embed] }); } }); client.on("error", (error) => { console.error("Client error:", error); }); process.on("unhandledRejection", (error) => { console.error("Unhandled rejection:", error); }); client.login(process.env.DISCORD_TOKEN);
Create the Environment File and Test
Create the .env file with your bot token, then run the bot to verify it works before setting up process management.
# Create the .env file echo "DISCORD_TOKEN=your-bot-token-here" > .env # Run the bot node bot.js
Once you see the ready message and have tested a command, press Ctrl+C to stop the bot. The next sections cover process management to keep it running permanently.
Using systemd to Keep Your Bot Running 24/7 (Python and Node.js)
systemd is the standard process manager built into every modern Linux distribution. It starts your bot automatically on boot, restarts it if it crashes, and provides logging through journalctl. This is the recommended approach for Python bots and works equally well for Node.js.
A systemd service file tells the system how to start, stop, and manage your bot process. Create one with the following command.
systemd Service File for a Python Bot
# Create the service file sudo nano /etc/systemd/system/discord-bot.service # Paste the following content: [Unit] Description=Discord Bot After=network.target [Service] Type=simple User=botuser WorkingDirectory=/home/botuser/discord-bot ExecStart=/home/botuser/discord-bot/venv/bin/python3 bot.py Restart=always RestartSec=10 EnvironmentFile=/home/botuser/discord-bot/.env StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
systemd Service File for a Node.js Bot
For Node.js bots, the service file is nearly identical. Only the ExecStart line changes to point at the Node.js binary.
[Unit] Description=Discord Bot After=network.target [Service] Type=simple User=botuser WorkingDirectory=/home/botuser/discord-bot ExecStart=/usr/bin/node bot.js Restart=always RestartSec=10 EnvironmentFile=/home/botuser/discord-bot/.env StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
Enable and Start the Service
After creating the service file, reload the systemd daemon, enable the service to start on boot, and start it immediately.
sudo systemctl daemon-reload sudo systemctl enable discord-bot sudo systemctl start discord-bot sudo systemctl status discord-bot
The status command should show "active (running)" in green. Your bot is now running as a background service and will survive reboots, SSH disconnections, and terminal closures.
Using pm2 to Keep Your Node.js Bot Running 24/7
pm2 is a popular process manager built specifically for Node.js applications. It provides automatic restarts, log management, and a monitoring dashboard. While systemd works perfectly for Node.js bots, pm2 offers a more Node.js-native experience with useful extras like cluster mode and a built-in log rotation module.
Install and Configure pm2
sudo npm install -g pm2 # Start your bot with pm2 cd ~/discord-bot pm2 start bot.js --name "discord-bot" # Save the process list so pm2 restarts it on reboot pm2 save # Generate the startup script for your OS pm2 startup systemd # Run the command pm2 outputs to enable boot persistence
Useful pm2 Commands
- pm2 status — shows all running processes with CPU and memory usage
- pm2 logs discord-bot — streams real-time logs from your bot
- pm2 restart discord-bot — restarts the bot process
- pm2 stop discord-bot — stops the bot without removing it from pm2
- pm2 delete discord-bot — removes the bot from pm2 entirely
- pm2 monit — opens the pm2 monitoring dashboard in your terminal
pm2 automatically restarts your bot if it crashes. By default it retries up to 16 times with an exponential backoff delay. You can customise this behaviour with a pm2 ecosystem configuration file for more advanced setups.
Setting Up Automatic Restarts on Crash
Both systemd and pm2 handle automatic restarts, but the configuration differs. Understanding the options lets you fine-tune the behaviour for your bot.
With systemd, the Restart=always directive in the service file means the service restarts regardless of why it stopped. The RestartSec=10 directive adds a 10-second delay between restarts to prevent rapid restart loops if your bot has a persistent error. You can also set a maximum number of restarts within a time window to prevent infinite crash loops.
Advanced systemd Restart Configuration
# Add these lines to the [Service] section of your service file Restart=always RestartSec=10 StartLimitIntervalSec=300 StartLimitBurst=5 # This allows 5 restarts within 300 seconds (5 minutes) # If the bot crashes more than 5 times in 5 minutes, # systemd stops trying and marks the service as failed
pm2 Ecosystem File for Advanced Restart Control
For pm2, create an ecosystem.config.js file in your bot directory for fine-grained control over restart behaviour, environment variables, and log settings.
// ecosystem.config.js module.exports = { apps: [ { name: "discord-bot", script: "bot.js", watch: false, max_restarts: 10, min_uptime: "10s", max_memory_restart: "200M", restart_delay: 5000, env: { NODE_ENV: "production", }, }, ], };
The max_memory_restart option is particularly useful for Discord bots. If your bot has a memory leak, pm2 automatically restarts it when memory usage exceeds the threshold, keeping your VPS stable. Start the bot using the ecosystem file with pm2 start ecosystem.config.js.
Monitoring Your Bot: Uptime, Logs, and Resource Usage
Deploying your bot is only half the job. Monitoring ensures you catch problems before your users report them. There are several layers of monitoring you should set up.
For systemd-managed bots, journalctl is your primary log viewer. It captures everything your bot prints to stdout and stderr, with timestamps and filtering capabilities.
Viewing Logs with journalctl
# View recent logs sudo journalctl -u discord-bot -n 50 # Follow logs in real time sudo journalctl -u discord-bot -f # View logs from the last hour sudo journalctl -u discord-bot --since "1 hour ago" # View logs from a specific date sudo journalctl -u discord-bot --since "2026-04-14 00:00:00"
Monitoring System Resources
Keep an eye on CPU and memory usage to ensure your bot is not consuming more resources than expected. The htop command provides a real-time, colour-coded overview of all processes.
# Install and run htop sudo apt install -y htop htop # Check memory usage free -h # Check disk usage df -h # Check bot-specific resource usage ps aux | grep bot.js ps aux | grep bot.py
Setting Up a Simple Uptime Monitor
External uptime monitoring services like UptimeRobot (free tier available) or BetterUptime can ping your server at regular intervals and notify you via email, SMS, or Discord webhook if it goes down. If your bot also runs a small HTTP health-check server, these services can monitor whether the bot process itself is running, not just the VPS.
For a Python bot, add a lightweight health-check endpoint using aiohttp alongside your discord.py bot.
# Add to your bot.py for a health-check endpoint from aiohttp import web async def health_check(request): return web.Response(text="OK") async def start_health_server(): app = web.Application() app.router.add_get("/health", health_check) runner = web.AppRunner(app) await runner.setup() site = web.TCPSite(runner, "0.0.0.0", 8080) await site.start() @bot.event async def on_ready(): print(f"{bot.user} is online!") await start_health_server()
Remember to open port 8080 in your firewall with sudo ufw allow 8080 if you set up a health-check endpoint. Point your uptime monitor at http://your-server-ip:8080/health and configure alerts to notify you via Discord webhook for full-circle monitoring.
Updating Your Bot Code on the VPS
When you push changes to your bot, you need a reliable way to deploy updates without extended downtime. If you cloned your bot from a Git repository, updating is straightforward.
# For systemd-managed bots cd ~/discord-bot git pull origin main source venv/bin/activate # Python only pip install -r requirements.txt # Python only npm install # Node.js only sudo systemctl restart discord-bot # For pm2-managed bots cd ~/discord-bot git pull origin main npm install pm2 restart discord-bot
The entire update process takes under 10 seconds. Your bot will be offline for only a moment during the restart. For zero-downtime deployments on larger bots, consider running two bot instances behind a load balancer, but this is overkill for most Discord bots.
Security Best Practices for Your Bot VPS
A VPS connected to the internet is a potential target. Follow these essential security practices to protect your bot and server.
Never run your bot as the root user. Use the dedicated botuser account created earlier. Keep your system updated by running sudo apt update && sudo apt upgrade regularly or enabling unattended security updates. Store your bot token in a .env file and never commit it to a public repository. If your token is ever exposed, regenerate it immediately from the Discord Developer Portal.
Set up SSH key-based authentication and disable password login for a stronger security posture. Fail2Ban can automatically block IP addresses that attempt too many failed SSH logins. Install it with sudo apt install fail2ban and it works out of the box with sensible defaults.
Need a Telegram bot too? Same VPS works for both. A single BearHost VPS can run multiple bots across different platforms simultaneously. Your Discord bot, Telegram bot, and any other services can all share the same server as long as resource usage stays within your plan limits.
Troubleshooting Common Issues
- Bot goes offline after closing SSH — You did not set up systemd or pm2. Running python3 bot.py or node bot.js directly in your terminal ties the process to your SSH session. Set up a process manager as described above.
- Bot crashes with "Too many restarts" — Your bot has a persistent error causing it to crash repeatedly. Check logs with sudo journalctl -u discord-bot -n 100 or pm2 logs discord-bot. Fix the underlying bug before restarting.
- Bot responds slowly or times out — Check resource usage with htop. If CPU or memory is consistently maxed out, upgrade your VPS plan. Also check your bot code for blocking operations that should be asynchronous.
- Cannot connect to Discord API — Verify your server has internet access with ping discord.com. Check that your firewall is not blocking outbound connections. Ensure your bot token in the .env file is correct and has not been revoked.
- Permission denied errors — Make sure the botuser owns all files in the bot directory with sudo chown -R botuser:botuser ~/discord-bot. Check that the virtual environment (Python) or node_modules (Node.js) was created by botuser, not root.
Frequently Asked Questions
Conclusion
Hosting a Discord bot on a VPS is the most reliable way to keep it online 24/7. The setup takes about 30 minutes, the resource requirements are minimal, and the monthly cost is less than a coffee. Whether you are building with Python and discord.py or Node.js and discord.js, the process follows the same pattern: provision a VPS, install your runtime, upload your code, and configure a process manager to handle crashes and reboots automatically. BearHost VPS plans at BearHost VPS Hosting start from $4.49 per month with full root access, NVMe SSD storage, and unmetered bandwidth — everything you need to run a Discord bot that never sleeps.