A Discord bot only works while its process is running. Close the laptop, lose the Wi-Fi or let Windows install an update overnight, and your moderation, music or ticket bot goes quiet until someone notices. Running it on a server fixes that: the bot stays connected, restarts on its own if it crashes, and you can still read its logs and change its files from anywhere. This guide covers how to set up a discord.js project so it is ready for a server, how to keep the token safe, and how to keep the bot running once it is live.
Why not just run it on your own PC?
You can, and for development you should. But a bot that people rely on needs to be up when you are asleep. A home machine has to stay switched on, its connection drops from time to time, and if the process crashes nobody restarts it. A small hosted container is quieter, cheaper to leave on than a desktop, and gives you a console you can check from your phone.
What resources a Node bot needs
Most bots are light. A bot that answers commands, assigns roles or posts messages spends most of its time waiting for events from Discord, so it needs little CPU and a modest amount of memory.
What pushes the requirements up:
- Server count. discord.js caches guilds, channels and members in memory, so a bot in many large servers holds more data.
- Caching choices. Fetching every member of every guild costs far more memory than caching only what you use.
- Extra work. Image generation, audio processing or a local database all add load on top of the bot itself.
Start small, watch the memory graph for a week, and size up only if it keeps climbing.
Setting up the project
A Node bot is an ordinary Node project. The parts that matter for hosting are package.json and a clear entry file.
package.json
Install discord.js with npm install discord.js, which adds it to dependencies. Commit both package.json and package-lock.json, so the server installs the same versions you tested. Add a start script that points at your entry file:
"main": the file that starts the bot, for exampleindex.js."scripts": { "start": "node index.js" }: the command a host or a teammate can run without reading your code.
Check the discord.js documentation for the minimum Node version it supports, and pick that version or newer on the server.
Keep the token out of your code
The bot token is the bot’s password. Anyone who has it can log in as your bot. Never paste it into index.js, and never commit it to a repository, public or private.
Read it from an environment variable instead:
- In code, use
process.env.DISCORD_TOKENand pass it toclient.login(). - Locally, keep it in a
.envfile loaded with a package such asdotenv, and add.envto.gitignore. - On the server, set it as a startup variable in the panel, so the token never lives in your files at all.
Before you push your code anywhere, search the project for your token. If it ever appears in a commit, treat it as leaked and reset it, even if you deleted the line afterwards.
Intents and permissions
Discord only sends your bot the events it asks for. In discord.js you list them when you create the client, using GatewayIntentBits such as Guilds and GuildMessages.
Three intents are privileged: Server Members, Presence and Message Content. They must be switched on under the Bot tab in the Discord Developer Portal before your bot can request them, and once a bot is verified it needs Discord’s approval to keep using them. Request only what the bot actually uses. Slash commands do not need Message Content, which is one good reason to build on them.
The same rule applies to permissions. When you generate the invite link, tick only the permissions the bot needs. A bot with Administrator is a much bigger problem if its token ever leaks.
Keeping it running and reading logs
On a server, two things keep a bot healthy: automatic restarts and logs you actually read.
- Restarts. If the process exits, the panel starts it again. That covers crashes, but it will not fix a bug that crashes on every start, so check the console after any restart loop.
- Logs. Everything your bot writes with
console.logandconsole.errorappears in the live console. Log the moment the client is ready, and log errors with enough detail to find the cause. - Unhandled errors. Listen for the client’s
errorevent and forunhandledRejectiononprocess, so a single failed API call is logged rather than taking the whole bot down.
Updating the bot
Treat updates like a small deployment:
- Test the change locally with your own test server.
- Upload the changed files over SFTP or the file manager.
- If you changed dependencies, upload the new
package.jsonandpackage-lock.json. - Restart from the panel and watch the console until the bot reports that it is ready.
When you upgrade discord.js itself across a major version, read its migration guide first. Major versions change APIs, and the bot will not start until the code matches.
Security habits worth keeping
- Reset the token if in doubt. In the Developer Portal, open the Bot tab and choose Reset Token. The old token stops working straight away, then you update the startup variable and restart.
- Use sub-users. If someone else helps maintain the bot, give them their own panel login with only the permissions they need, rather than sharing yours.
- Keep dependencies current. Run
npm outdatedfrom time to time and update deliberately, not all at once on a Friday night.
Backups
The code should live in git, but the server often holds things git does not: a SQLite database, config files, logs and uploaded assets. On GGHOST Cloud, backups run on a schedule you set and restore from the panel without a ticket. Take a manual backup before a big update as well, so a bad migration is a quick rollback.
Getting your bot on GGHOST Cloud
Bot hosting is set up on request, so we can size it to what your bot does.
- Tell us about the bot. Ask us on Discord (or open a ticket) with what you need: the Node version, roughly how many servers the bot is in, and anything extra it runs.
- Get a quote. We size it, quote a monthly price, and set it up on our Pterodactyl panel, usually within a few days.
- Upload your code over SFTP or the file manager. Dependencies install from
package.jsonon boot. - Add the token as a startup variable, start the server and watch the console for the ready message.
You get the full panel at panel.gghost.cloud: live console and logs, file manager, SFTP, startup variables, scheduled tasks and sub-users, with auto-restart if the process exits. Every node is behind DDoS protection from our network providers. Live regions today are Singapore and Europe (France–Germany border), with the United States (East, Central and West), the United Kingdom, India, Japan and Australia on demand. There is no setup fee and no contract, billing is at app.gghost.cloud, and support comes from the people who run the servers, on Discord or at hello@gghost.cloud.
The short version
Keep the token in an environment variable, never in code. Commit package.json and the lockfile, add a start script, and request only the intents and permissions you use. Log errors instead of letting them crash the process, back up anything that is not in git, and let the server handle restarts so your bot stays online when your PC does not.