#
Using Environment Variables
A .env
file is a type of file that holds environment variables of an application. Environment variables allow you to easily integrate your bot with various online platforms (ex. Heroku), easily split your production and development environment as well as keep important information like your bot token, API tokens and database details secure.
You do not want this information to get out to anyone. And using environment variables in a .env
file is one of the best ways to secure your information, being preferred over a config.json
file.
To start out, it's suggested you install the dotenv
package from NPM. This allows you to easily integrate environment variables into your bot. You may do that via the console. Make sure you are in your bot's root directory. Run this command:
npm install dotenv
Once installed, you will need to create a .env
file. I'll create an example one here (I will be using the CLIENT_TOKEN
variable from the master branch of discord.js).
If using v12 branch of discord.js, use DISCORD_TOKEN=
.
CLIENT_TOKEN=[YOUR_BOT_TOKEN]
OWNER=[YOUR_OWNER_ID]
PREFIX=[DEFAULT_BOT_PREFIX]
After you create and update this file, save it and head over to your main file. I will build off of the default Discord.js example code.
const { Client } = require("discord.js");
// Importing this allows you to access the environment variables of the running node process
require("dotenv").config();
const client = new Client();
// "process.env" accesses the environment variables for the running node process. PREFIX is the environment variable you defined in your .env file
const prefix = process.env.PREFIX;
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on("messageCreate", message => {
// Here's I'm using one of An Idiot's Guide's basic command handlers. Using the PREFIX environment variable above, I can do the same as the bot token below
if (message.author.bot) return;
if (message.content.indexOf(prefix.length) !== 0) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "ping") {
message.reply("Pong!");
}
});
// Here you can login the bot. It automatically attempts to login the bot with the environment variable you set for your bot token (either "CLIENT_TOKEN" or "DISCORD_TOKEN")
client.login();
This is all you will need to get off the ground. Now I will explain why this is important and why you should use environment variables with a .env
file over a config.json
file.
#
Using Git (ex. GitHub)
If you're going to publish your code with Git to a site like GitHub, then it's imperative you secure information by making sure your .env
isn't committed to a repository. You may do that using a .gitignore
file. Simply add the .env
file to the .gitignore
file in your local repository.
From there on out, any future commits will ignore that file or any other files or directories in .gitignore
. You can set up a .env.example
file in its place, but that's not always necessary.
.env
Following this, all users will see in your bot code is process.env.ENV_VARIABLE
which exposes nothing!
#
Using Heroku
Heroku is a website that allows you to start out and host your applications for free. In this case, your Discord bot. However, Heroku requires that you use environment variables. If you setup your files with the dotenv
package and required the specific environment variables in your code, then all you have to do is go the environment variables in your Heroku application and add the key and value.
In Heroku, these variables are called "Config Vars". I'm not going to go in-depth here about Heroku, but the same way you setup your .env
file, you would add in new environment variables in Heroku.
The only way your bot token can be exposed along with other environment variables is if you do one or more of these things:
- a) You accidentally expose your
.env
file because you didn't add it to.gitignore
- b) You added a collaborator through Heroku. A collaborator has almost full permissions as the app owner
Both a and b can be controlled. It's just you need to be smart.
#
Set environment variables in the start script
When starting your application, either locally on your computer, in a npm start script in your package.json
or even in a Dockerfile
you can set what environment your bot should run in.
For example, you may want to run your bot in production on Heroku or Glitch and in development on your computer. You can simply do that via adding new scripts in your package.json
.
Upon doing npm init
when you first made your bot, you should have seen a test
script created. The scripts portion of your package.json
should look like this if you added nothing.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
},
Here, you can add multiple scripts. Where going to add a few scripts. production
, development
, and start
.
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node .",
"production": "NODE_ENV=production&&npm start",
"development": "set NODE_ENV=development&&npm start"
},
- To start your bot in a production environment, you would do
npm run production
. This will setprocess.env.NODE_ENV
toproduction
- To start your bot in a development environment, you would do
npm run development
. This will setprocess.env.NODE_ENV
todevelopment
In your code, you can define what should happen depending on the environment loaded. Here's an example where your bot should only show the stream status if the environment is in production
when the ready
event is fired:
require("dotenv").config();
// process.env.NODE_ENV allows you to get the environment the node process is in
let ver = process.env.NODE_ENV;
client.on("ready", () => {
if (ver === "production") {
client.user.setActivity("An Idiot's Guide", { type: "STREAMING", url: "https://twitch.tv/something" })
}
else {
client.user.setActivity("in code land", { type: "PLAYING" });
}
});
Here I make sure that the bot is set to a streaming status only if my node environment is in production
. I don't want my bot shown as streaming while I'm working on it in a development environment. There is a lot more you can do with this though.
For example, you can change the production
and development
scripts to use entirely different main files if you wish. But I won't get into that here.
If you don't want to use start scripts, you can always set the node environment directly in the command line. Here's how:
# Windows
SET NODE_ENV=development&&npm start
SET NODE_ENV=development&&node .
SET NODE_ENV=development&&node app.js
# Linux/MacOS
NODE_ENV=development&&npm start
NODE_ENV=development&&node .
NODE_ENV=development&&node app.js
Either running these commands directly through the command line or in start scripts should work. It's entirely up to you. But for ease of use when deploying your bot, you should use start scripts. So for example, in Heroku, you can add this in your Procfile
:
# Heroku will run the bot in production mode
worker npm run production
If you're using Glitch, you can add this in your start
script in your package.json
:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "NODE_ENV=production&&node app.js"
},
You may need to change the name of the main file depending on what you called it/where it's located in your bot project.
#
More information
Here are some links to more information you can read regarding environment variables and Git if you aren't that familiar with it:
- Using Git to share and update code (An Idiot's Guide)
- Working with Environment Variables in Node.js (Twilio Blog)
dotenv
NPMdotenv-flow
NPM (Used for multiple.env
file)