Step 1
Install base packages and a deploy user
Update Ubuntu, install Git and build tools, then create a non-root user for the bot. Running application code as root is unnecessary and makes mistakes more expensive.
ssh root@<your-server-ip>
apt update && apt upgrade -y
apt install -y git curl build-essential logrotate
adduser bot
usermod -aG sudo botStep 2
Install Node with nvm
Install nvm as the bot user so Node versions stay isolated from the OS package manager. Use the current LTS unless your bot requires a specific version.
su - bot
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
. ~/.nvm/nvm.sh
nvm install --lts
node --version
npm --versionStep 3
Deploy the bot code
Clone your repository and install dependencies. This example assumes a Node bot with npm scripts. If your bot is TypeScript, build it before starting PM2 or point PM2 at the compiled output.
git clone https://github.com/you/your-discord-bot.git ~/bot
cd ~/bot
npm ci
npm run build --if-presentStep 4
Store secrets outside Git
Do not put the Discord token in the repository or process command line. Store it in an environment file readable by the bot user. You can use the same pattern for database URLs, API keys, and guild IDs.
exit
mkdir -p /etc/unode-bots
cat >/etc/unode-bots/discord-bot.env <<'EOF'
DISCORD_TOKEN=replace-with-your-token
NODE_ENV=production
EOF
chown root:bot /etc/unode-bots/discord-bot.env
chmod 640 /etc/unode-bots/discord-bot.envStep 5
Run the bot with PM2
PM2 manages restarts and logs. Load the environment file before starting. If your entry point is different, adjust npm start or ecosystem.config.js accordingly.
su - bot
. ~/.nvm/nvm.sh
cd ~/bot
set -a
. /etc/unode-bots/discord-bot.env
set +a
npm install -g pm2
pm2 start npm --name discord-bot -- start
pm2 save
pm2 startup systemd -u bot --hp /home/botStep 6
Add log rotation
Bots can log aggressively when Discord reconnects or a command loops. PM2 has a logrotate module that keeps logs bounded. Also send structured application logs to stdout so PM2 captures them consistently.
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 14
pm2 logs discord-botStep 7
Deploy updates safely
Pull code, install dependencies, rebuild if needed, and restart. If your bot serves many communities, test updates in a staging guild first. Discord tokens should be rotated if they ever appear in logs, screenshots, or Git history.
su - bot
cd ~/bot
git pull
npm ci
npm run build --if-present
pm2 restart discord-bot