To host a Discord bot on a VPS, create the bot application in the Discord Developer Portal, choose a small Linux VPS, secure the server, install Python and a virtual environment, upload the bot code, store the bot token in a protected environment file, run the application with systemd, and configure monitoring and backups. A basic text or slash-command bot can run on 1 vCPU and 1–2 GB RAM, while music, AI, databases, browser automation, and large community bots require more resources.
This tutorial deploys a Python bot using discord.py on Ubuntu 26.04 LTS. It uses slash commands, so the basic example does not require the privileged Message Content intent. The bot runs as a dedicated unprivileged Linux user and restarts automatically through systemd.
Never publish the bot token. A Discord bot token authenticates the application. If it appears in a public repository, screenshot, log, support ticket, or chat message, reset it immediately in the Developer Portal and update the VPS secret.
What You Will Build
By the end of this guide, you will have:
- A Discord application and bot user.
- A Linux VPS with secure SSH access.
- A Python virtual environment.
- A working
/pingslash command. - A protected environment file containing the bot token.
- A systemd service that runs the bot continuously.
- Logs available through the system journal.
- Basic update, monitoring, backup, and recovery procedures.
Discord Bot VPS Requirements
| Bot type | vCPU | RAM | Storage | Notes |
|---|---|---|---|---|
| Small slash-command bot | 1 shared vCPU | 1 GB | 10–20 GB SSD | Good for testing and a small server |
| Moderate community bot | 1–2 vCPU | 2 GB | 20–40 GB SSD | Commands, moderation, SQLite, and logs |
| Multi-server bot with database | 2–4 vCPU | 4–8 GB | 40–100 GB NVMe | PostgreSQL, Redis, analytics, or dashboards |
| Music or media-processing bot | 2–4+ vCPU | 4–8 GB+ | 40 GB+ | May require FFmpeg and more network capacity |
| AI or browser-automation bot | Workload specific | 8 GB+ | 60 GB+ | Model APIs, local inference, or headless browsers increase demand |
These are starting points. The number of guilds does not determine resource use by itself. Event volume, cache size, database queries, command frequency, voice connections, external APIs, and background tasks matter more.
Why Use a VPS for a Discord Bot?
A VPS runs independently from your personal computer. The bot remains online when your laptop is closed, your home internet disconnects, or you are away.
Advantages include:
- Continuous operation.
- Stable data-center network.
- Remote administration through SSH.
- Static IP address.
- Control over Python packages and services.
- System logs and monitoring.
- Scheduled backups.
- Easy scaling to a larger plan.
- Ability to run a database or web dashboard.
A VPS is not automatically managed. On an unmanaged plan, you are responsible for operating-system updates, SSH security, firewall rules, bot deployment, monitoring, and backups.
VPS vs Serverless vs Bot Hosting Platform
| Option | Best for | Main limitation |
|---|---|---|
| VPS | Long-running Gateway connection, custom dependencies, databases | You manage the operating system |
| Managed bot platform | Fast deployment and minimal administration | Platform limits and less control |
| Serverless functions | HTTP interactions and short request processing | Not ideal for a permanent Gateway process without specialized architecture |
| Home computer | Local development and testing | Unreliable for continuous public operation |
| Dedicated server | Many bots, voice, large databases, intensive processing | Higher cost for small workloads |
Most small and medium bots fit a VPS. A dedicated server becomes useful only when the workload consumes substantial CPU, RAM, storage, or network resources. Read What Is Dedicated Server Hosting? before paying for an entire physical machine.
Step 1: Create a Discord Application
- Sign in to the Discord Developer Portal.
- Create a new application.
- Enter a clear application name.
- Open the bot configuration page.
- Add or configure the bot user.
- Set the bot name and optional avatar.
- Review whether the bot should be publicly installable.
The application stores the bot configuration, installation settings, OAuth credentials, and token. Use an owner account protected with multi-factor authentication.
Create or reset the bot token
Generate the token from the bot page and copy it into a secure password manager temporarily. Do not place it directly in source code. The guide will store it in a root-controlled environment file on the VPS.
If the token is exposed:
- Reset it in the Developer Portal.
- Update the environment file on the VPS.
- Restart the systemd service.
- Review logs and repository history.
- Remove the secret from commits and cached build output.
Step 2: Configure Installation Scopes and Permissions
For a server-installed bot with slash commands, configure the installation to use the bot and applications.commands scopes. Select only the permissions required by the bot.
The example /ping command needs permission to view the channel and send a response. A moderation bot may need permissions such as Manage Messages or Moderate Members. Do not give Administrator permission simply because it is convenient.
Apply least privilege
- Request only permissions the current features use.
- Document why each permission is required.
- Separate the bot’s role from human administrator roles.
- Place the bot role correctly in the server role hierarchy.
- Review permissions after adding or removing features.
- Use command checks so sensitive commands work only for authorized members.
Step 3: Understand Gateway Intents
Gateway intents control which event groups a bot receives. Enable only the intents needed by the application.
Common privileged intents include:
- Message Content: needed when the bot reads ordinary message text for prefix commands or content analysis.
- Server Members: needed for selected member-list and member-event features.
- Presence: needed for selected online-status and activity information.
The example in this guide uses slash commands and default intents, so it does not need Message Content. If you later add !command-style prefix commands, you may need to enable Message Content in both the Developer Portal and the code.
Large or verified applications can face additional approval requirements for privileged intents. Design the bot to collect only the data required for its function.
Step 4: Invite the Bot to Your Discord Server
- Open the application installation settings.
- Select Guild Install.
- Add the
botandapplications.commandsscopes. - Select the minimum bot permissions.
- Copy or use the generated installation link.
- Choose a Discord server where you have permission to add applications.
- Authorize the requested permissions.
The bot appears offline until its code connects successfully from the VPS.
Step 5: Choose the Right VPS
For the example bot, choose:
- 1 vCPU.
- 1–2 GB RAM.
- 20 GB SSD or NVMe storage.
- Ubuntu 26.04 LTS or Ubuntu 24.04 LTS.
- A public IP address.
- A provider console or rescue environment.
- Automatic backup or snapshot options.
Choose a server location
Discord bots connect to Discord infrastructure over the internet, and the location also affects database, API, and dashboard latency. Choose a region with reliable routing and proximity to the bot’s main external dependencies.
Use How to Choose the Best Server Location and Best Server Location for Low Latency when comparing regions.
Choose Linux unless the bot requires Windows
Linux normally uses fewer resources and has no Windows Server license cost. Ubuntu and Debian are common for Python and Node.js bots. Review Best Server OS in 2026 if the application has unusual platform requirements.
Step 6: Connect to the VPS
Connect through SSH:
ssh root@SERVER_IP
Replace SERVER_IP with the address from the provider. Verify the host-key fingerprint when possible.
Create a named administrator:
adduser adminuser
usermod -aG sudo adminuser
Copy existing SSH keys:
rsync --archive --chown=adminuser:adminuser ~/.ssh /home/adminuser
Open a second terminal and test:
ssh adminuser@SERVER_IP
sudo whoami
Keep the root session open until the new account works.
Step 7: Update and Secure the VPS
Update packages:
sudo apt update
sudo apt upgrade -y
sudo apt autoremove --purge -y
Install the firewall and allow SSH before enabling it:
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status verbose
A Discord bot using the Gateway normally makes outbound connections and does not require an inbound application port. Open another port only when the bot provides a web dashboard, webhook receiver, health endpoint, or API.
Test port access using Port Ping: How to Ping a Specific Port when troubleshooting a dashboard or webhook service.
Harden SSH
After key authentication works, create a drop-in file:
sudo nano /etc/ssh/sshd_config.d/99-bot-server.conf
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
AllowUsers adminuser
Validate and reload:
sudo sshd -t
sudo systemctl reload ssh
Confirm a new SSH session works before closing the current one.
Step 8: Install Python and Required Tools
Install Python, virtual-environment support, Git, and basic tools:
sudo apt install -y python3 python3-venv python3-pip git curl
Check versions:
python3 --version
git --version
A virtual environment isolates the bot’s packages from the operating system. Do not install application packages globally with sudo pip.
Step 9: Create a Dedicated Bot User
The bot should not run as root or as your administrator account. Create a system user:
sudo useradd --system --create-home \
--home-dir /opt/discordbot \
--shell /usr/sbin/nologin \
discordbot
Create the application directory and set ownership:
sudo mkdir -p /opt/discordbot
sudo chown -R discordbot:discordbot /opt/discordbot
The nologin shell prevents normal interactive login as the service user. systemd can still start the application under that account.
Step 10: Upload or Clone the Bot Code
For a Git repository:
sudo -u discordbot git clone REPOSITORY_URL /opt/discordbot/app
Use a private deploy key or access token with the minimum repository permissions. Do not place a personal full-access token in the Git remote URL or shell history.
Teams managing private repositories can review How to Run Your Own Git Server for self-hosted source control concepts.
For the tutorial, create the application directory manually:
sudo -u discordbot mkdir -p /opt/discordbot/app
sudo nano /opt/discordbot/app/bot.py
Step 11: Create the Discord Bot Code
Paste this slash-command example into /opt/discordbot/app/bot.py:
import logging
import os
import sys
import discord
from discord import app_commands
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
stream=sys.stdout,
)
logger = logging.getLogger("zoomnod-discord-bot")
class BotClient(discord.Client):
def __init__(self) -> None:
intents = discord.Intents.default()
super().__init__(intents=intents)
self.tree = app_commands.CommandTree(self)
async def setup_hook(self) -> None:
commands = await self.tree.sync()
logger.info("Synced %s application commands", len(commands))
async def on_ready(self) -> None:
logger.info("Connected as %s (ID: %s)", self.user, self.user.id)
client = BotClient()
@client.tree.command(name="ping", description="Check whether the bot is online")
async def ping(interaction: discord.Interaction) -> None:
latency_ms = round(client.latency * 1000)
await interaction.response.send_message(
f"Pong! Gateway latency: {latency_ms} ms",
ephemeral=True,
)
token = os.environ.get("DISCORD_TOKEN")
if not token:
raise RuntimeError("DISCORD_TOKEN is not configured")
client.run(token, log_handler=None)
This example:
- Uses default, non-privileged intents.
- Registers a global
/pingslash command. - Reads the token from an environment variable.
- Writes logs to standard output for systemd journal collection.
- Returns the current Gateway heartbeat latency.
Global application commands can take time to become visible everywhere. During development, many teams sync commands to one test guild for faster iteration, then switch to global commands before release.
Step 12: Create the Python Virtual Environment
Create the environment as the bot user:
sudo -u discordbot python3 -m venv /opt/discordbot/venv
Upgrade packaging tools and install discord.py:
sudo -u discordbot /opt/discordbot/venv/bin/python -m pip install --upgrade pip
sudo -u discordbot /opt/discordbot/venv/bin/pip install --upgrade discord.py
Save the tested package versions:
sudo -u discordbot /opt/discordbot/venv/bin/pip freeze \
| sudo tee /opt/discordbot/app/requirements.lock >/dev/null
A lock file makes rebuilds more reproducible. Test library updates in a separate environment before applying them to a production bot.
Step 13: Store the Bot Token Securely
Create a protected environment file outside the code repository:
sudo nano /etc/discordbot.env
Add:
DISCORD_TOKEN=PASTE_THE_BOT_TOKEN_HERE
Protect the file:
sudo chown root:discordbot /etc/discordbot.env
sudo chmod 640 /etc/discordbot.env
Do not put quotes around the token unless the selected environment parser requires them. Do not add the file to Git.
Protect every related secret
The bot may also use database passwords, API keys, webhook secrets, encryption keys, and OAuth credentials. Store each secret outside the repository, restrict access, and rotate it after suspected exposure.
Step 14: Test the Bot Manually
Load the environment file into a temporary root-controlled shell and run the bot as its service user:
sudo bash -c '
set -a
source /etc/discordbot.env
set +a
exec sudo -u discordbot \
/opt/discordbot/venv/bin/python \
/opt/discordbot/app/bot.py
'
Look for a successful connection message. Open Discord and test /ping. Stop the manual process with Ctrl+C.
If the bot remains offline
Check:
- The token is current.
- The bot was invited to the correct server.
- The VPS can reach the internet.
- The system time is correct.
- The Python package installed successfully.
- The environment variable is available.
- Required intents are enabled in both code and the Developer Portal.
- DNS resolution works.
Step 15: Run the Discord Bot 24/7 with systemd
Create a service:
sudo nano /etc/systemd/system/discordbot.service
Paste:
[Unit]
Description=Discord Bot
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=discordbot
Group=discordbot
WorkingDirectory=/opt/discordbot/app
EnvironmentFile=/etc/discordbot.env
ExecStart=/opt/discordbot/venv/bin/python /opt/discordbot/app/bot.py
Restart=on-failure
RestartSec=5
TimeoutStopSec=30
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
[Install]
WantedBy=multi-user.target
Reload systemd and start the bot:
sudo systemctl daemon-reload
sudo systemctl enable --now discordbot
sudo systemctl status discordbot
The service starts automatically after reboot and restarts after an unexpected application failure. It does not restart continuously after a normal intentional stop.
When the bot needs writable storage
ProtectSystem=full makes system locations read-only but leaves selected application paths writable according to normal permissions. Create a dedicated data directory:
sudo mkdir -p /opt/discordbot/data
sudo chown discordbot:discordbot /opt/discordbot/data
Configure the application to store SQLite databases, caches, and generated files there. Avoid writing temporary data into the source-code directory when deployments replace that directory.
Step 16: View Discord Bot Logs
View recent logs:
sudo journalctl -u discordbot -n 100 --no-pager
Follow logs live:
sudo journalctl -u discordbot -f
Show logs from the current boot:
sudo journalctl -u discordbot -b
Check failed services:
systemctl --failed
Logs should not contain the bot token, database passwords, private message content, or unnecessary personal data. Redact secrets from exception messages before sending logs to third parties.
Step 17: Configure Monitoring and Alerts
Monitoring should verify more than whether the VPS responds to ping.
Track:
- systemd service state.
- Bot connection and reconnect events.
- Command error rate.
- Gateway latency.
- API rate-limit warnings.
- CPU and memory use.
- Disk capacity.
- Database availability.
- External API failures.
- Backup success.
- Operating-system reboot requirements.
Use Best Linux System Monitor in 2026 to compare infrastructure monitoring tools. Broader management options are covered in The Best Server Management Tool.
Create a health signal
A small bot can send a heartbeat to an external uptime service or update a health record periodically. Larger bots should expose metrics or a protected health endpoint showing process state, event-loop responsiveness, database connectivity, and last successful Gateway event.
Step 18: Handle Discord Rate Limits Correctly
Discord applies route-specific and global API rate limits. Mature libraries such as discord.py handle normal rate-limit responses. Do not bypass the library with uncontrolled HTTP requests or create loops that repeatedly send, edit, delete, or react to messages.
Use these practices:
- Let the library schedule API requests.
- Queue bulk operations.
- Add cooldowns to commands that can create repeated actions.
- Cache data when appropriate.
- Avoid polling information available through Gateway events.
- Use exponential backoff for external APIs.
- Record HTTP 429 and reconnect events.
- Do not retry immediately in an infinite loop.
Ignoring rate limits can cause temporary restrictions or loss of API access. Design commands so one user cannot trigger thousands of actions.
Step 19: Add Command Permissions and Error Handling
Every command should validate who can run it, where it can run, and what inputs it accepts. Sensitive moderation, configuration, billing, or administrative commands should require explicit Discord permissions, roles, or owner checks.
Handle:
- Missing Discord permissions.
- Invalid command arguments.
- Database failures.
- External API timeouts.
- Deleted channels or roles.
- Rate limits.
- Unexpected exceptions.
Return a short user-friendly message and log the technical error with a correlation identifier. Do not expose stack traces, secrets, internal paths, or database queries to Discord users.
Step 20: Back Up the Bot
Back up:
- Source code or repository references.
- Locked dependency versions.
- Database data.
- Application configuration.
- systemd service file.
- Deployment and recovery instructions.
- Encryption keys through a secure process.
Do not copy the Discord token into an ordinary unencrypted archive. Store secrets in a protected credential system and document how to rotate them.
Follow How to Back Up and Restore Data on a VPS for backup schedules, retention, off-server storage, and restore testing.
Step 21: Update the Discord Bot Safely
A Git-based deployment can use this process:
sudo systemctl stop discordbot
sudo -u discordbot git -C /opt/discordbot/app pull --ff-only
sudo -u discordbot /opt/discordbot/venv/bin/pip install \
-r /opt/discordbot/app/requirements.lock
sudo systemctl start discordbot
sudo systemctl status discordbot
sudo journalctl -u discordbot -n 50 --no-pager
Before updating production:
- Back up the database and configuration.
- Review the code changes.
- Test in a development Discord server.
- Check dependency release notes.
- Define a rollback commit or release.
- Verify commands and permissions after restart.
For a larger bot, use versioned releases and an automated deployment pipeline instead of pulling directly into production.
Step 22: Configure Automatic Security Updates
Install and verify unattended security upgrades:
sudo apt install unattended-upgrades -y
sudo unattended-upgrade --dry-run --debug
Check whether a reboot is required:
test -f /run/reboot-required && echo "Reboot required"
Schedule reboots and verify that systemd brings the bot back online. Monitor the service after operating-system and Python package updates.
Step 23: Add a Database When the Bot Outgrows Files
A small bot can use SQLite for configuration and modest data. Use PostgreSQL or another server database when you need concurrent access, stronger query capabilities, replication, a web dashboard, or multiple bot instances.
| Storage option | Best for | Limitation |
|---|---|---|
| JSON or YAML file | Very small static configuration | Weak concurrency and migration controls |
| SQLite | Small single-process bot | Limited multi-instance write concurrency |
| PostgreSQL | Production relational data | Requires administration or managed service |
| Redis | Cache, queues, cooldowns, temporary state | Not a replacement for every persistent database |
Bind databases to localhost or a private network. Do not expose the database port publicly unless a specific secured architecture requires it.
Step 24: Scale a Large Discord Bot
Large bots can require sharding, distributed workers, queues, caches, and separate services. Discord Gateway sharding divides guild connections among sessions. The library and Discord configuration must agree on shard behavior.
Possible architecture:
- One or more Gateway bot processes.
- PostgreSQL database.
- Redis cache and task queue.
- Background worker processes.
- Web dashboard or API.
- Centralized logs and metrics.
- Load balancer for HTTP services.
- Automated deployment and rollback.
Do not add distributed complexity before monitoring shows a real bottleneck. A single well-configured VPS can support many practical bots.
Discord Bot Security Checklist
- The Discord owner account uses multi-factor authentication.
- The bot token is not stored in source code.
- The environment file has restricted permissions.
- The bot runs as an unprivileged Linux user.
- SSH uses keys and direct root login is disabled.
- The firewall exposes only required inbound ports.
- The bot requests minimum Discord permissions.
- Privileged intents are enabled only when required.
- Dependencies are pinned and reviewed.
- Commands enforce authorization and cooldowns.
- Logs do not expose secrets or unnecessary personal data.
- Backups are stored off-server and tested.
- The provider account uses multi-factor authentication.
- A token-rotation and incident-response process exists.
Endpoint protection can add another layer for selected workloads. Compare options in Best Antivirus Software for Servers.
Common Discord Bot Hosting Problems
The bot is offline
Check the token, service status, journal logs, DNS, internet connectivity, and Developer Portal configuration.
sudo systemctl status discordbot
sudo journalctl -u discordbot -n 100 --no-pager
Slash commands do not appear
Confirm the bot was installed with application-command permissions, the code synchronized commands successfully, and the application is installed in the correct server. Global commands can require propagation time.
Prefix commands do not respond
Message-based commands may require the Message Content intent in the Developer Portal and in code. Confirm the bot can view the channel and read messages.
Permission errors
Check the bot’s server role, channel overrides, requested installation permissions, and role hierarchy. Administrator permission should not be the default fix.
The service restarts repeatedly
Inspect the first exception in the journal. Common causes include a missing token, syntax error, dependency mismatch, inaccessible file, database failure, or invalid configuration.
High memory use
Review caches, event handlers, database result sets, large guild-member data, media processing, and background tasks. Restarting hides the problem temporarily but does not fix a memory leak.
The VPS disk is full
Check journals, application logs, databases, caches, temporary files, and old deployments:
df -h
sudo du -xhd1 /var /opt 2>/dev/null | sort -h
Set retention limits and disk alerts before the filesystem fills.
Discord Bot Deployment Checklist
- The bot application exists in the Developer Portal.
- The token is stored securely.
- Installation scopes and permissions are correct.
- Required Gateway intents are enabled.
- The VPS has enough CPU, RAM, and storage.
- The operating system is supported and updated.
- SSH and firewall settings are secured.
- The bot runs as a dedicated service user.
- Python packages are isolated in a virtual environment.
- The application starts manually.
- The systemd service starts and restarts correctly.
- Logs are available and do not contain secrets.
- Monitoring detects an offline bot.
- Database and application backups are tested.
- Updates have a rollback procedure.
Common Mistakes to Avoid
- Putting the token in Git: use a protected environment file or secret manager.
- Running the bot as root: use a dedicated unprivileged account.
- Giving Administrator permission: request only what the bot needs.
- Enabling every privileged intent: minimize collected events and approval requirements.
- Using screen or tmux as the only process manager: systemd provides restart, boot, and logging integration.
- Opening unnecessary firewall ports: a Gateway bot usually needs outbound access only.
- Ignoring rate limits: use the library’s request handling and command cooldowns.
- Updating directly in production without testing: use a test server and rollback plan.
- Keeping the only database copy on the VPS: use off-server backups.
- Logging message content and tokens: minimize sensitive data collection.
- Buying an oversized server: start small and monitor real resource use.
- Running a user account as a bot: use an official bot application and bot token.
Final Verdict
A 1 vCPU Linux VPS with 1–2 GB RAM is enough for many small Discord bots. The most important deployment choices are secure token storage, least-privilege Discord permissions, a dedicated Linux service user, a systemd process, monitored logs, and tested backups.
Start with slash commands and default Gateway intents unless the bot genuinely needs message content, member lists, or presence data. Monitor CPU, memory, database performance, reconnects, and command errors. Upgrade the VPS only when measurements show a limit.
Frequently Asked Questions
Can I host a Discord bot on a VPS?
Yes. A VPS is well suited to a long-running Discord Gateway connection and gives you control over Python, Node.js, databases, logs, and process management.
How much RAM does a Discord bot need?
A small bot can run with 1 GB RAM. Two GB provides safer headroom, while databases, music, AI, browser automation, and large caches may require 4 GB or more.
Which VPS operating system is best for a Discord bot?
Ubuntu LTS and Debian are common choices because they are stable, well documented, and support current Python and Node.js tools.
How do I keep a Discord bot running 24/7?
Run it as a systemd service with restart settings, enable the service at boot, and monitor its status from an external system.
Does a Discord bot need an open inbound port?
A normal Gateway bot does not. It makes outbound connections. Open inbound ports only for a web dashboard, webhook receiver, API, or health endpoint.
Where should I store the Discord bot token?
Store it in a protected environment file or secret manager outside the source repository. Restrict file access to the service process.
Does a slash-command bot need Message Content intent?
No. A basic slash-command bot can operate without reading ordinary message content. Enable privileged intents only for features that require them.
Can I use screen or tmux to run the bot?
You can use them for temporary testing, but systemd is better for production because it supports boot startup, restarts, service status, and journal logs.
How much does Discord bot VPS hosting cost?
A small unmanaged Linux VPS commonly costs about $4–$15 per month. Larger bots require more RAM, dedicated CPU, databases, backups, or management.
What should I do if the bot token is leaked?
Reset it immediately in the Developer Portal, update the VPS secret, restart the service, remove the token from repositories and logs, and review unauthorized activity.
Latest Hosting Guides
VPS Hosting for Kubernetes: Complete Guide for 2026
VPS Hosting for Docker Containers: Complete Guide for 2026
VPS Hosting for Redis: Complete Guide for 2026
VPS Hosting for Elasticsearch: Complete Guide for 2026
Forex Dedicated Server: How to Choose the Best Low-Latency Trading Server in 2026
Swipe or scroll to explore more guides