A Discord bot that can run commands on your game server is a remote console whose password is "has the right role in Discord". That can be a perfectly good design - staff already live in Discord, and kicking a griefer from a phone is genuinely useful - but only if the bot runs a short allow-list of commands rather than anything typed at it, checks roles on every command, has the smallest Discord permissions it can work with, logs every use, and keeps its token and the RCON password out of reach. For one-way traffic such as status and alerts, a webhook is simpler and safer than any bot.
This post covers the integrations game servers commonly use, the risks specific to admin bots, how to set permissions properly on both sides, and a small, safe admin bot you can run yourself. One-way status messages are covered in Discord webhooks for server status, and hosting a bot of any kind is covered in host a Discord bot 24/7.
Webhook, integration or your own bot#
Pick the least powerful tool that does the job.
| Need | Tool | Can it change the server? |
|---|---|---|
| Status, alerts, join announcements | Webhook | No |
| Chat bridge between game and Discord | Game-side integration | Limited to chat |
| Console in a Discord channel | Game-side integration | Yes, everything |
| Whitelist requests, kicks, a few commands | Admin bot with an allow-list | Only what you allow |
| Discord moderation itself | Discord AutoMod, a moderation bot | No, Discord only |
A webhook can only post. It holds no credentials for your game server, so the worst thing a leaked webhook URL can do is post spam into one channel. That makes it the right choice for anything one-way: status embeds, crash alerts, restart notices, ban announcements.
A bot is a long-running program connected to Discord with a token, and it can do whatever its code and its permissions allow. The moment it can talk to the game server's console, its security matters as much as your RCON password's.
The integrations game servers commonly use#
Most popular games have a well-trodden integration, and using it is usually better than writing your own.
- Minecraft - DiscordSRV. A plugin on the server that bridges game chat and a Discord channel, links Discord and Minecraft accounts, syncs roles, and can mirror the console into a channel where messages are run as commands. That last feature is the one to think about carefully. DiscordSRV for Minecraft covers the setup.
- FiveM - txAdmin. txAdmin includes a Discord bot that can post a persistent server status embed and handle whitelist requests, so players can request access from Discord and staff approve them in txAdmin. FiveM server and txAdmin covers txAdmin itself, and FiveM Discord permissions and whitelist covers role-based access.
- Source games and CS2. SourceMod and CounterStrikeSharp plugins commonly post reports, bans and chat to Discord through webhooks; admin actions themselves stay in game.
- Rust, DayZ, Arma and other RCON games. Admin tools and RCON services connect to the server over RCON and often have their own Discord features: kill feeds, ban notices, player lists. They hold your RCON password, so they deserve the same scrutiny as a bot you write.
- Generic status bots. Bots that query the server's public status port and show players online. They need nothing secret, because the information is public. Query ports and A2S explains what they read.
Why a console bot is an RCON with a different lock#
Picture what an attacker needs to run commands on your server through each route.
The panel console is behind your account and its two-factor. RCON is behind one password. A console bot is behind a Discord role - which means it is behind every Discord account that has that role, the security of each of those accounts, and everyone who can assign roles in your Discord. A compromised staff Discord account, a moderator who gives themselves a role they should not have, or a bot with the "Administrator" permission that someone else takes over, all lead to your server console.
The specific risks:
- Role escalation inside Discord. Anyone with "Manage Roles" can give themselves any role below their own highest role. If the console role is low in the list, more people can reach it than you think.
- Mirrored console channels. A channel where every message is run as a console command, readable and writable by a role, is the most dangerous configuration available. It also shows the console output, which on Minecraft includes players' IP addresses on every join.
- Bot token theft. A token in a public repository, a pasted config file or a compromised host gives the thief the bot, with all its permissions in your Discord and whatever it can do to your server. Discord resets tokens it detects in public GitHub repositories, which tells you how often this happens.
- Unchecked input. A bot that passes whatever text a user types to the console allows command chaining and arbitrary commands, even if you only meant to allow
kick.
Permissions done properly, on both sides#
On the Discord side:
- Give the bot its own role with only the permissions it uses. A status or admin bot typically needs to view a few channels, send messages and embed links. Leave out Administrator, Manage Server, Manage Roles and Manage Webhooks unless a specific feature needs one.
- Put the staff role that controls the bot high in the role list, and limit who has Manage Roles, so it cannot be self-assigned.
- Use channel permission overrides so the bot's admin commands are only usable in a staff channel.
- Require two-factor for moderation in Discord's server safety settings, which makes Discord require 2FA on accounts that use moderation permissions.
- Use slash commands with default permissions, so the command is hidden from people without the right Discord permission unless you deliberately change that.
On the game side:
- Give the bot its own RCON password if the game allows it, or at least a password that is not the one staff use, and change it when the bot changes hands.
- Allow-list commands in the bot, not block-list them.
list,kick,whitelist addare fine. Anything that takes free text into a console -sayis the usual exception - needs its input checked. - On games with permission systems, run the bot as a limited identity. Minecraft plugins such as DiscordSRV can restrict console commands from Discord to an allow-list in their config; use that rather than open console access.
- Log every command the bot runs, with the Discord user who asked for it, to a channel staff can read but not edit.
RCON safely covers the RCON side in more depth, including which games let you restrict it at all.
A small admin bot you can trust#
If you need a handful of admin commands from Discord and your game has standard Source-style RCON (Minecraft, Rust in legacy mode, Source games, many others), a bot this size is enough and easy to audit. It uses discord.py 2.x and the rcon package from PyPI.
import osimport discordfrom discord import app_commandsfrom rcon.source import rconGUILD = discord.Object(id=int(os.environ["GUILD_ID"]))LOG_CHANNEL = int(os.environ["LOG_CHANNEL_ID"])STAFF_ROLE = "Server Staff"ALLOWED = {"list", "kick", "whitelist"}client = discord.Client(intents=discord.Intents.default())tree = app_commands.CommandTree(client)async def run(*args: str) -> str: return await rcon(*args, host=os.environ["RCON_HOST"], port=int(os.environ["RCON_PORT"]), passwd=os.environ["RCON_PASSWORD"])@tree.command(name="server", description="Run an allowed server command", guild=GUILD)@app_commands.default_permissions(kick_members=True)@app_commands.checks.has_role(STAFF_ROLE)async def server(interaction: discord.Interaction, command: str): parts = command.split() if not parts or parts[0] not in ALLOWED: await interaction.response.send_message("Not allowed.", ephemeral=True) return await interaction.response.defer(ephemeral=True) result = await run(*parts) await interaction.followup.send(f"```\n{result[:1800]}\n```", ephemeral=True) log = client.get_channel(LOG_CHANNEL) if log: await log.send(f"{interaction.user} ran `{command}`")@tree.errorasync def on_error(interaction: discord.Interaction, error): if isinstance(error, app_commands.MissingRole): await interaction.response.send_message("Staff only.", ephemeral=True)@client.eventasync def on_ready(): await tree.sync(guild=GUILD)client.run(os.environ["DISCORD_TOKEN"])What makes it safe enough:
- Slash commands only. It never reads ordinary messages, so it does not need the privileged message content intent, and nobody can trigger it by typing in a channel.
- Two checks.
default_permissionshides the command from members without Kick Members, andhas_rolerefuses anyone without the staff role even if a server admin changes the command's visibility. - An allow-list on the first word. Only
list,kickandwhitelistcan run. Add commands one at a time, deliberately. - Arguments passed separately. The command is split into words and sent as separate arguments, rather than pasted into the console as one string.
- Every use logged to a channel, with the person who ran it.
- No secrets in code. The token, RCON password and IDs come from environment variables.
Extend it with dedicated commands - /kick player reason with typed parameters - rather than a growing free-text allow-list, once you know which commands staff actually use.
Sending logs to Discord without leaking them#
Logs in Discord are convenient and also a privacy problem, because Discord channels are easy to read and easy to screenshot.
- Send events, not raw console. "Steve was banned by Anna: x-ray" is useful. A raw console mirror includes IP addresses, plugin errors and anything else the server prints.
- Keep staff logs in staff channels, with the permissions checked. A log channel accidentally visible to
@everyoneis a common way players' addresses end up public. - Respect rate limits. Discord limits how fast a bot or webhook can post; batch log lines into one message every few seconds instead of one message per line. The webhooks post covers the 429 handling.
- Do not treat Discord as your log archive. The real logs stay on the server, with a retention period - server logs worth keeping covers that, and game server privacy and player data covers why it matters.
Hosting the bot, and its token#
A bot needs to run all the time, which means it should not run on someone's gaming PC. A small app hosting plan is enough: a bot like the one above uses well under the smallest plan's memory. On RE:NODE, the Python and Node.js lines start at 1 GB, environment variables for the token and passwords go on the Startup tab, and Git deploy can pull the bot's code from a private GitHub repository on start - Discord.py bot hosting guide has the step-by-step, and the app hosting page has the plans.
Treat the token like a password:
- Never commit it. Keep it in an environment variable and add any local
.envfile to.gitignore. Environment variables and secrets covers the pattern. - Reset it immediately if it leaks, from the Discord developer portal. The old token stops working at once.
- Limit who can see the bot's hosting. Anyone with file or settings access to the bot's server can read its token. Panel subusers can be given console access without settings or file access.
- Know who owns the application. A bot owned by one staff member's personal Discord account leaves with them. Discord's developer teams let several people manage an application without sharing an account.
When something goes wrong#
If the bot starts doing things nobody asked for, or you suspect its token or the RCON password leaked:
- Reset the bot token in the developer portal.
- Change the RCON password on the game server, and update the bot's environment variable.
- Check Discord's audit log for role and permission changes, and the bot's log channel for commands you do not recognise.
- Check the game server for admin entries, bans, whitelist changes or files you did not make. What to do when your server is hacked covers the full order of work.
FAQ#
Is DiscordSRV's console channel safe to use?
It is as safe as the channel's permissions and the accounts that can write in it. Restrict it to a few trusted staff, require two-factor for moderators in Discord, and use its configuration to limit which commands can be run from Discord. For most communities, staff are better served by the panel console.
Should my bot use RCON or a game plugin?
A plugin can integrate more closely and often has finer permissions; RCON works with any game that supports it and keeps the bot separate from the server. For a small admin bot, RCON with an allow-list is simpler to audit.
Can a bot run on the same plan as the game server?
Run it separately. A bot on its own small app plan keeps running when the game server restarts or crashes, which is exactly when you want status and alerts, and it keeps the bot's token away from people who have access to the game server's files.
Do I need the message content intent?
Not for slash commands. It is a privileged intent needed to read the text of ordinary messages. A bot that only uses slash commands does not need it, and is safer for not having it.
What permissions does a status bot need?
View the channel, send messages and embed links, and read message history if it edits its own message. It needs nothing that touches roles, members or server settings.




Comments
Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.