What are environment variables?

Environment variables are key-value pairs stored outside your source code that configure how your application runs. For Discord bots, they store sensitive values like your bot token, database credentials, and API keys. They also store configuration that changes between environments, like a command prefix or log level.

The core principle is simple: secrets and configuration that vary between environments do not belong in your code. They belong in the environment where the code runs.

Why environment variables matter for Discord bots

  • Security: Your bot token in source code means anyone who sees the code controls your bot. Environment variables keep secrets out of your codebase entirely.
  • Portability: The same code runs on your local machine, MonkeyBytes, a VPS, or any other platform. Only the environment variables change.
  • Version control safety: With secrets in environment variables, you can safely push your code to GitHub without exposing credentials.
  • Team safety: Each developer uses their own test bot token. No one needs access to the production token except the production server.

Setting up .env files

Node.js with dotenv

npm install dotenv

Create .env in your project root:

DISCORD_TOKEN=MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.AbCdEf.GhIjKlMnOpQrStUvWxYz
PREFIX=!
OWNER_ID=123456789012345678
DATABASE_URL=sqlite:./data/bot.db
LOG_LEVEL=info

Load at the top of your entry file:

require('dotenv').config();

// Access variables
const token = process.env.DISCORD_TOKEN;
const prefix = process.env.PREFIX || '!';
const ownerId = process.env.OWNER_ID;

Python with python-dotenv

pip install python-dotenv

Same .env file format, loaded with:

import os
from dotenv import load_dotenv

load_dotenv()

token = os.getenv('DISCORD_TOKEN')
prefix = os.getenv('PREFIX', '!')
owner_id = int(os.getenv('OWNER_ID', '0'))

.env file rules

  • No spaces around the = sign
  • No quotes needed unless the value contains spaces
  • One variable per line
  • Lines starting with # are comments
  • Empty lines are ignored
# Discord configuration
DISCORD_TOKEN=your_token_here
PREFIX=!

# Database
DATABASE_URL=sqlite:./data/bot.db

# Feature flags
ENABLE_MUSIC=true
ENABLE_MODERATION=true

Keeping .env out of version control

Your .gitignore must exclude all environment files:

# Environment variables - NEVER commit these
.env
.env.*
*.env
.env.local
.env.production

If you have already committed a .env file, removing it from the current code is not enough. It remains in git history. You must consider any tokens in that file compromised and regenerate them immediately. See our security guide for token regeneration steps.

Environment variables on different platforms

MonkeyBytes Hosting

Upload your .env file via SFTP to the root of your project directory. The file is stored within your isolated container and is not accessible to anyone else. Your bot reads it exactly as it does locally.

VPS (Linux)

You can use .env files, or set variables directly in your process manager:

# PM2 ecosystem file
module.exports = {
  apps: [{
    name: 'my-bot',
    script: 'index.js',
    env: {
      DISCORD_TOKEN: 'your_token',
      PREFIX: '!'
    }
  }]
};
# systemd service file
[Service]
EnvironmentFile=/home/botuser/my-bot/.env

Heroku

Set via CLI or dashboard:

heroku config:set DISCORD_TOKEN=your_token

Railway

Set in the Variables tab of your service dashboard. Railway injects them into the runtime automatically.

Common variables for Discord bots

VariablePurposeExample
DISCORD_TOKENBot authentication tokenMTIz...WxYz
PREFIXCommand prefix!
OWNER_IDBot owner's Discord user ID123456789
GUILD_IDTest server ID (for dev commands)987654321
DATABASE_URLDatabase connection stringsqlite:./bot.db
LOG_LEVELLogging verbosityinfo
NODE_ENVRuntime environmentproduction

Multiple environments

Use separate .env files for development and production:

.env.development    # Local testing with test bot token
.env.production     # Production bot token (never on your local machine)

Load the correct file based on context:

// Node.js
require('dotenv').config({
    path: process.env.NODE_ENV === 'production'
        ? '.env.production'
        : '.env.development'
});

Validating environment variables

Your bot should check that required variables exist at startup rather than crashing later with a cryptic error:

// Node.js validation
const required = ['DISCORD_TOKEN', 'OWNER_ID'];
const missing = required.filter(key => !process.env[key]);

if (missing.length > 0) {
    console.error(`Missing required environment variables: ${missing.join(', ')}`);
    console.error('Create a .env file with these variables. See the deployment guide.');
    process.exit(1);
}
# Python validation
import sys

required = ['DISCORD_TOKEN', 'OWNER_ID']
missing = [key for key in required if not os.getenv(key)]

if missing:
    print(f'Missing required environment variables: {", ".join(missing)}')
    print('Create a .env file with these variables. See the deployment guide.')
    sys.exit(1)

For complete deployment instructions, read our Node.js deployment guide or Python deployment guide. For comprehensive security practices including token management, see our security guide.

GuideSecurity Best Practices GuideNode.js Deployment GuidePython Deployment Getting StartedDeploy Your Bot