Running a Discord Bot on a VPS: Node.js vs. Python Setup Guide for 2026
A Discord bot that only runs when your computer is on is barely useful. Members test the bot at 3 AM and it doesn't respond. The solution: host it on a VPS and let it run 24/7. This guide covers both Node.js (discord.js) and Python (discord.py) setups.
Prerequisites
- A Space-Node VPS (smallest plan works for most bots)
- SSH access
- Your bot code repository (GitHub, GitLab, or local zip)
Node.js Bot Deployment
# Install Node.js 20 LTS (Ubuntu)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install nodejs
# Clone your bot
git clone https://github.com/yourusername/your-discord-bot.git /home/bot/
cd /home/bot/
# Install dependencies
npm install
# Test run
node index.js
Python Bot Deployment
# Install Python 3.11+
sudo apt install python3 python3-pip python3-venv
# Create virtual environment
python3 -m venv /home/bot/venv
source /home/bot/venv/bin/activate
# Clone and install
git clone https://github.com/yourusername/your-discord-bot.git /home/bot/code
cd /home/bot/code
pip install -r requirements.txt
# Test run
python3 bot.py
Keeping the Bot Running with PM2
PM2 manages the process lifecycle:
# Install PM2
npm install -g pm2
# Start Node.js bot
pm2 start index.js --name my-discord-bot
# OR Python bot
pm2 start "python3 /home/bot/code/bot.py" --name my-discord-bot
# Save process list and enable on startup
pm2 save
pm2 startup # Follow the output instruction
Managing Environment Variables Securely
Never put your Discord token in your source code. Use environment variables:
# Create .env file (NOT committed to git)
cat > /home/bot/.env << 'EOF'
DISCORD_TOKEN=your_token_here
DATABASE_URL=your_db_url_here
EOF
# Load in Node.js:
require('dotenv').config({ path: '/home/bot/.env' })
const token = process.env.DISCORD_TOKEN
# Load in Python:
from dotenv import load_dotenv
load_dotenv('/home/bot/.env')
token = os.getenv('DISCORD_TOKEN')
Updating Your Bot
cd /home/bot/code/
git pull origin main
pm2 restart my-discord-bot
Set up a GitHub webhook to automate this, or run it manually after each push.