หลายคนเริ่มเขียน Discord Bot บนเครื่องตัวเอง พอปิดคอม บอทก็ offline ทันที บทความนี้จะพาย้ายบอทขึ้น Linux VPS (Ubuntu) แล้วตั้งให้รันเป็น systemd service — บอทจะ restart เองเมื่อ crash และกลับมาออนไลน์เองหลัง reboot โดยไม่ต้องพึ่ง tool เสริม
คำสั่งทั้งหมดเขียนสำหรับ Ubuntu 22.04/24.04 ครับ
สิ่งที่ต้องมี
- Linux VPS 1 เครื่อง (Ubuntu) ที่เข้า SSH ได้ บอทเล็ก ๆ ใช้ทรัพยากรน้อยมาก สเปกเริ่มต้นของผู้ให้บริการส่วนใหญ่ก็พอ ถ้าแค่อยากลองก่อนโดยยังไม่ผูกรายเดือน มีผู้ให้บริการที่ให้เช่าแบบรายวัน เช่น VPSKUB (เช่ารายวัน/รายสัปดาห์/รายเดือน มี Ubuntu ให้เลือก) หรือใช้เจ้าไหนก็ได้ที่คุ้นเคย
- Discord Application + Bot Token จาก Discord Developer Portal
- Client ID ของแอป และ Guild ID (Server ID) ของเซิร์ฟเวอร์ที่ใช้ทดสอบ (เปิด Developer Mode ใน Discord แล้วคลิกขวาที่เซิร์ฟเวอร์ → Copy Server ID)
1) เตรียมเครื่อง: update + firewall
SSH เข้าเครื่อง (เปลี่ยน YOUR_SERVER_IP เป็น IP ของคุณ):
ssh root@YOUR_SERVER_IP
อัปเดตแพ็กเกจและเปิด firewall แบบอนุญาตเฉพาะ SSH:
apt update && apt upgrade -y
apt install -y ufw git curl
ufw allow OpenSSH
ufw enable
ufw status
Discord Bot ทั่วไปเชื่อมต่อ ขาออก ไปยัง Discord Gateway เท่านั้น จึงไม่ต้องเปิด port ขาเข้าเพิ่ม (ยกเว้นคุณทำ web dashboard หรือ webhook server เอง)
2) สร้าง user แยกสำหรับรันบอท
อย่ารันบอทด้วย root — ถ้าโค้ดหรือ dependency มีช่องโหว่ ความเสียหายจะจำกัดอยู่ที่ user นี้:
adduser --system --group --home /opt/mybot mybot
3) ติดตั้ง Node.js LTS
ใช้ repository ของ NodeSource (Node 22 LTS):
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt install -y nodejs
node -v
npm -v
4) สร้างโปรเจกต์บอท
cd /opt/mybot
sudo -u mybot npm init -y
sudo -u mybot npm install discord.js
สร้างไฟล์ .env เก็บ secret (ห้าม commit ขึ้น Git):
sudo -u mybot tee /opt/mybot/.env > /dev/null <<'ENV'
DISCORD_TOKEN=ใส่_bot_token_ตรงนี้
CLIENT_ID=ใส่_application_id
GUILD_ID=ใส่_server_id
ENV
chmod 600 /opt/mybot/.env
index.js — ตัวบอท
// /opt/mybot/index.js
const { Client, Events, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (c) => {
console.log(`Ready! Logged in as ${c.user.tag}`);
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply(`Pong! 🏓 (${client.ws.ping} ms)`);
}
});
client.login(process.env.DISCORD_TOKEN);
deploy-commands.js — ลงทะเบียน slash command
// /opt/mybot/deploy-commands.js
const { REST, Routes, SlashCommandBuilder } = require('discord.js');
const commands = [
new SlashCommandBuilder().setName('ping').setDescription('เช็คว่าบอทยังอยู่ไหม'),
].map((c) => c.toJSON());
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
(async () => {
await rest.put(
Routes.applicationGuildCommands(process.env.CLIENT_ID, process.env.GUILD_ID),
{ body: commands },
);
console.log('Slash commands registered.');
})();
ให้สิทธิ์ไฟล์แก่ user mybot แล้วทดสอบ (Node 20.6+ อ่าน .env ได้เองด้วย --env-file):
chown mybot:mybot /opt/mybot/*.js
cd /opt/mybot
sudo -u mybot node --env-file=.env deploy-commands.js
sudo -u mybot node --env-file=.env index.js
ถ้าเห็น Ready! Logged in as ... ลองพิมพ์ /ping ใน Discord ได้เลย จากนั้นกด Ctrl+C เพื่อหยุด — ขั้นต่อไปเราจะให้ systemd ดูแลแทน
5) ตั้งเป็น systemd service
tee /etc/systemd/system/mybot.service > /dev/null <<'UNIT'
[Unit]
Description=My Discord Bot
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/opt/mybot/.env
ExecStart=/usr/bin/node index.js
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now mybot
systemctl status mybot
Restart=on-failure = crash แล้วเริ่มใหม่ใน 5 วินาที, enable = เปิดเองหลัง reboot
6) ดู log และอัปเดตโค้ด
journalctl -u mybot -f # ดู log แบบ real-time
journalctl -u mybot --since "1 hour ago"
systemctl restart mybot # หลังแก้โค้ด
ถ้าเก็บโค้ดบน GitHub ขั้นตอน deploy ง่าย ๆ คือ:
cd /opt/mybot
sudo -u mybot git pull
sudo -u mybot npm ci --omit=dev
systemctl restart mybot
Troubleshooting ที่เจอบ่อย
| อาการ | สาเหตุ / วิธีแก้ |
|---|---|
TokenInvalid / An invalid token was provided
|
token ผิด หรือเพิ่ง reset token ใน Developer Portal → แก้ .env แล้ว systemctl restart mybot
|
พิมพ์ /ping แล้วไม่ขึ้นคำสั่ง |
ยังไม่ได้รัน deploy-commands.js หรือ GUILD_ID ผิด |
Used disallowed intents |
ใช้ intent อย่าง MessageContent หรือ GuildMembers แต่ยังไม่ได้เปิดในหน้า Bot ของ Developer Portal |
service ขึ้น failed ทันที |
ดู journalctl -u mybot -n 50 ส่วนใหญ่คือ path ผิด หรือ user mybot ไม่มีสิทธิ์อ่านไฟล์ |
Security checklist สั้น ๆ
- ใช้ SSH key แทนรหัสผ่าน แล้วตั้ง
PasswordAuthentication noใน/etc/ssh/sshd_config -
chmod 600 .envและใส่.envใน.gitignoreเสมอ — token หลุดขึ้น GitHub สาธารณะคือเคสที่เจอบ่อยมาก - ติดตั้ง security update อัตโนมัติ:
apt install -y unattended-upgrades - ถ้า token เคยหลุด ให้กด Reset Token ทันที
สรุป
แค่ Ubuntu + Node.js + systemd ก็ได้บอทที่ออนไลน์ 24/7, restart ตัวเองเมื่อ crash และดู log ได้ด้วย journalctl โดยไม่ต้องติดตั้ง process manager เพิ่ม วิธีเดียวกันนี้ใช้กับบอท Python (discord.py) ได้เลย แค่เปลี่ยน ExecStart เป็น path ของ Python ใน virtualenv
อ่านต่อ (ภาษาไทย): การเลือกสเปก VPS สำหรับ Discord Bot ตามขนาดบอท
Disclosure: ผมเป็นผู้ดูแล VPSKUB ที่ลิงก์ไว้ในบทความ แต่ขั้นตอนทั้งหมดใช้ได้กับ Ubuntu VPS ทุกเจ้า













