Keeping Secrets Out of Your Discloud Upload: Using discloud.config and Environment Variables
Learn how to keep Discord bot tokens out of your Discloud upload by using discloud.config for deployment metadata and per‑app environment variables for secrets.
14 Mar 2026, 09:47 UTC

The problem: a config file becomes a secret leak
When you first scaffold a Discord bot, it’s common to store the bot token in a JSON or .env file and commit that file to your repository. On Discloud the entire project folder is zipped and uploaded as the deployment artifact. If that configuration file lives inside the zip, anyone who can download the artifact—whether through a shared link, a compromised account, or a log that exposes the URL—gets immediate access to your token.
Thesis: treat the zip as immutable code, move runtime configuration out of it
Instead of baking secrets into the archive, keep the zip as pure, version‑controlled code. Put deployment‑specific instructions in a file named discloud.config that lives at the root of the zip. This file is read by Discloud at upload time and tells the platform how to run your app (entry point, memory limit, restart policy, etc.). Secrets and any values that may change between environments are supplied as per‑app environment variables set in the Discloud dashboard or via its API. Those variables are injected into the process at start‑up, never written to disk, and can be updated without rebuilding the zip.
Worked example: a Node.js bot
Assume a simple bot whose entry file is index.js:
// index.js
require('dotenv').config(); // only loads .env locally
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once('ready', () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.login(process.env.DISCORD_TOKEN);
// optional prefix for commands, also from env
const PREFIX = process.env.PREFIX || '!';
During local development you may keep a .env file:
# .env (never committed)
DISCORD_TOKEN=your_token_here
PREFIX=!
To make sure this file never ends up in the upload, add it to .gitignore and to the Discloud ignore list (the platform respects .gitignore when creating the zip). Your package.json can include a prepare step that builds a clean archive, but a simple manual check works too:
- Run
npm packorzip -r bot.zip . -x "*.git*" "*.env" "node_modules/*"to create the archive. - Inspect the contents:
unzip -l bot.zipshould showdiscloud.configat the top level and no.env. - If you see any unwanted files, adjust your ignore patterns and repeat.
The discloud.config file (JSON format) might look like this:
{
"main": "index.js",
"runtime": "nodejs-18",
"memory": 256,
"restart": "always"
}
After you upload the zip, go to the app’s settings in the Discloud dashboard and add two environment variables:
DISCORD_TOKEN– your bot token (keep it secret)PREFIX– optional command prefix
When Discloud starts the container, it injects those variables into the process, so process.env.DISCORD_TOKEN resolves to the value you set in the dashboard. The same zip can be redeployed to a staging app with a different token simply by changing the variable; no rebuild is needed.
Trade‑offs and limitations
Environment variables on Discloud are a flat key‑value store:
- No version history – if you overwrite a variable, the previous value is lost.
- No namespacing – you cannot easily separate "dev", "staging", and "prod" values without using different apps or custom prefixes.
- No audit trail in the UI – you must rely on external change‑management or manual notes.
- Values are only read at process start; rotating a token requires a restart of the app.
These limits are usually acceptable for a bot because secrets change infrequently and a restart is harmless. If you need fine‑grained promotion flows or automatic rotation, you would have to layer an external secret manager and fetch values at runtime, which adds complexity.
Action checklist
- Add
discloud.configat the project root with your entry point, runtime, memory, and restart settings. - Ensure
.env,node_modules, and any build artifacts are excluded from the zip (via.gitignoreor explicit zip flags). - Verify locally: unzip the archive and
grep -r "DISCORD_TOKEN" .should return no matches. - Upload the zip, set the same variables in the dashboard, and start the app.
- Check the logs: you should see the bot’s ready message and no trace of the token.
- When you need to change a token or prefix, edit the variable in the dashboard and restart the app; confirm the change appears in the logs or bot behavior.
By keeping the deployment artifact free of secrets and using Discloud’s environment‑variable mechanism, you gain a repeatable, auditable upload process while reducing the risk of accidental credential exposure.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.