<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: VPS KUB</title>
    <description>The latest articles on DEV Community by VPS KUB (@vps_kub_6ce76bc4f6817a886).</description>
    <link>https://dev.to/vps_kub_6ce76bc4f6817a886</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4200072%2Fb9b6d463-1a1f-4665-9f88-2f8284b72062.jpg</url>
      <title>DEV Community: VPS KUB</title>
      <link>https://dev.to/vps_kub_6ce76bc4f6817a886</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vps_kub_6ce76bc4f6817a886"/>
    <language>en</language>
    <item>
      <title>รัน Discord Bot (discord.js v14) บน Linux VPS ให้ออนไลน์ 24 ชม. ด้วย systemd — ทีละขั้นแบบใช้ได้จริง</title>
      <dc:creator>VPS KUB</dc:creator>
      <pubDate>Thu, 22 Oct 2026 09:04:23 +0000</pubDate>
      <link>https://dev.to/vps_kub_6ce76bc4f6817a886/ran-discord-bot-discordjs-v14-bn-linux-vps-aihnailn-24-chm-dwy-systemd-thiilakhanaebbaichaidcchring-3ikb</link>
      <guid>https://dev.to/vps_kub_6ce76bc4f6817a886/ran-discord-bot-discordjs-v14-bn-linux-vps-aihnailn-24-chm-dwy-systemd-thiilakhanaebbaichaidcchring-3ikb</guid>
      <description>&lt;p&gt;หลายคนเริ่มเขียน Discord Bot บนเครื่องตัวเอง พอปิดคอม บอทก็ offline ทันที บทความนี้จะพาย้ายบอทขึ้น &lt;strong&gt;Linux VPS (Ubuntu)&lt;/strong&gt; แล้วตั้งให้รันเป็น &lt;strong&gt;systemd service&lt;/strong&gt; — บอทจะ restart เองเมื่อ crash และกลับมาออนไลน์เองหลัง reboot โดยไม่ต้องพึ่ง tool เสริม&lt;/p&gt;

&lt;p&gt;คำสั่งทั้งหมดเขียนสำหรับ Ubuntu 22.04/24.04 ครับ&lt;/p&gt;

&lt;h2&gt;
  
  
  สิ่งที่ต้องมี
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Linux VPS 1 เครื่อง (Ubuntu) ที่เข้า SSH ได้ บอทเล็ก ๆ ใช้ทรัพยากรน้อยมาก สเปกเริ่มต้นของผู้ให้บริการส่วนใหญ่ก็พอ ถ้าแค่อยากลองก่อนโดยยังไม่ผูกรายเดือน มีผู้ให้บริการที่ให้เช่าแบบรายวัน เช่น &lt;a href="https://vpskub.com/" rel="noopener noreferrer"&gt;VPSKUB&lt;/a&gt; (เช่ารายวัน/รายสัปดาห์/รายเดือน มี Ubuntu ให้เลือก) หรือใช้เจ้าไหนก็ได้ที่คุ้นเคย&lt;/li&gt;
&lt;li&gt;Discord Application + Bot Token จาก &lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Client ID ของแอป และ Guild ID (Server ID) ของเซิร์ฟเวอร์ที่ใช้ทดสอบ (เปิด Developer Mode ใน Discord แล้วคลิกขวาที่เซิร์ฟเวอร์ → Copy Server ID)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1) เตรียมเครื่อง: update + firewall
&lt;/h2&gt;

&lt;p&gt;SSH เข้าเครื่อง (เปลี่ยน &lt;code&gt;YOUR_SERVER_IP&lt;/code&gt; เป็น IP ของคุณ):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@YOUR_SERVER_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;อัปเดตแพ็กเกจและเปิด firewall แบบอนุญาตเฉพาะ SSH:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; ufw git curl
ufw allow OpenSSH
ufw &lt;span class="nb"&gt;enable
&lt;/span&gt;ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Discord Bot ทั่วไปเชื่อมต่อ &lt;strong&gt;ขาออก&lt;/strong&gt; ไปยัง Discord Gateway เท่านั้น จึงไม่ต้องเปิด port ขาเข้าเพิ่ม (ยกเว้นคุณทำ web dashboard หรือ webhook server เอง)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2) สร้าง user แยกสำหรับรันบอท
&lt;/h2&gt;

&lt;p&gt;อย่ารันบอทด้วย root — ถ้าโค้ดหรือ dependency มีช่องโหว่ ความเสียหายจะจำกัดอยู่ที่ user นี้:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adduser &lt;span class="nt"&gt;--system&lt;/span&gt; &lt;span class="nt"&gt;--group&lt;/span&gt; &lt;span class="nt"&gt;--home&lt;/span&gt; /opt/mybot mybot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3) ติดตั้ง Node.js LTS
&lt;/h2&gt;

&lt;p&gt;ใช้ repository ของ NodeSource (Node 22 LTS):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://deb.nodesource.com/setup_22.x | bash -
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs
node &lt;span class="nt"&gt;-v&lt;/span&gt;
npm &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4) สร้างโปรเจกต์บอท
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/mybot
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot npm &lt;span class="nb"&gt;install &lt;/span&gt;discord.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สร้างไฟล์ &lt;code&gt;.env&lt;/code&gt; เก็บ secret (&lt;strong&gt;ห้าม&lt;/strong&gt; commit ขึ้น Git):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot &lt;span class="nb"&gt;tee&lt;/span&gt; /opt/mybot/.env &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="sh"&gt;'
DISCORD_TOKEN=ใส่_bot_token_ตรงนี้
CLIENT_ID=ใส่_application_id
GUILD_ID=ใส่_server_id
&lt;/span&gt;&lt;span class="no"&gt;ENV
&lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 /opt/mybot/.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  index.js — ตัวบอท
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /opt/mybot/index.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GatewayIntentBits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;discord.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;intents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;GatewayIntentBits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Guilds&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;once&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ClientReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Ready! Logged in as &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;InteractionCreate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isChatInputCommand&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;commandName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Pong! 🏓 (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ms)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DISCORD_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  deploy-commands.js — ลงทะเบียน slash command
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// /opt/mybot/deploy-commands.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;REST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SlashCommandBuilder&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;discord.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SlashCommandBuilder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;เช็คว่าบอทยังอยู่ไหม&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;REST&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;setToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DISCORD_TOKEN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applicationGuildCommands&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GUILD_ID&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;commands&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Slash commands registered.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ให้สิทธิ์ไฟล์แก่ user &lt;code&gt;mybot&lt;/code&gt; แล้วทดสอบ (Node 20.6+ อ่าน &lt;code&gt;.env&lt;/code&gt; ได้เองด้วย &lt;code&gt;--env-file&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;mybot:mybot /opt/mybot/&lt;span class="k"&gt;*&lt;/span&gt;.js
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/mybot
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot node &lt;span class="nt"&gt;--env-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.env deploy-commands.js
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot node &lt;span class="nt"&gt;--env-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.env index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าเห็น &lt;code&gt;Ready! Logged in as ...&lt;/code&gt; ลองพิมพ์ &lt;code&gt;/ping&lt;/code&gt; ใน Discord ได้เลย จากนั้นกด &lt;code&gt;Ctrl+C&lt;/code&gt; เพื่อหยุด — ขั้นต่อไปเราจะให้ systemd ดูแลแทน&lt;/p&gt;

&lt;h2&gt;
  
  
  5) ตั้งเป็น systemd service
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tee&lt;/span&gt; /etc/systemd/system/mybot.service &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;UNIT&lt;/span&gt;&lt;span class="sh"&gt;'
[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
&lt;/span&gt;&lt;span class="no"&gt;UNIT

&lt;/span&gt;systemctl daemon-reload
systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; mybot
systemctl status mybot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Restart=on-failure&lt;/code&gt; = crash แล้วเริ่มใหม่ใน 5 วินาที, &lt;code&gt;enable&lt;/code&gt; = เปิดเองหลัง reboot&lt;/p&gt;

&lt;h2&gt;
  
  
  6) ดู log และอัปเดตโค้ด
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; mybot &lt;span class="nt"&gt;-f&lt;/span&gt;          &lt;span class="c"&gt;# ดู log แบบ real-time&lt;/span&gt;
journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; mybot &lt;span class="nt"&gt;--since&lt;/span&gt; &lt;span class="s2"&gt;"1 hour ago"&lt;/span&gt;
systemctl restart mybot         &lt;span class="c"&gt;# หลังแก้โค้ด&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ถ้าเก็บโค้ดบน GitHub ขั้นตอน deploy ง่าย ๆ คือ:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/mybot
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot git pull
&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; mybot npm ci &lt;span class="nt"&gt;--omit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dev
systemctl restart mybot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting ที่เจอบ่อย
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;อาการ&lt;/th&gt;
&lt;th&gt;สาเหตุ / วิธีแก้&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;TokenInvalid&lt;/code&gt; / &lt;code&gt;An invalid token was provided&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;token ผิด หรือเพิ่ง reset token ใน Developer Portal → แก้ &lt;code&gt;.env&lt;/code&gt; แล้ว &lt;code&gt;systemctl restart mybot&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;พิมพ์ &lt;code&gt;/ping&lt;/code&gt; แล้วไม่ขึ้นคำสั่ง&lt;/td&gt;
&lt;td&gt;ยังไม่ได้รัน &lt;code&gt;deploy-commands.js&lt;/code&gt; หรือ &lt;code&gt;GUILD_ID&lt;/code&gt; ผิด&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Used disallowed intents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ใช้ intent อย่าง &lt;code&gt;MessageContent&lt;/code&gt; หรือ &lt;code&gt;GuildMembers&lt;/code&gt; แต่ยังไม่ได้เปิดในหน้า Bot ของ Developer Portal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;service ขึ้น &lt;code&gt;failed&lt;/code&gt; ทันที&lt;/td&gt;
&lt;td&gt;ดู &lt;code&gt;journalctl -u mybot -n 50&lt;/code&gt; ส่วนใหญ่คือ path ผิด หรือ user &lt;code&gt;mybot&lt;/code&gt; ไม่มีสิทธิ์อ่านไฟล์&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Security checklist สั้น ๆ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ใช้ SSH key แทนรหัสผ่าน แล้วตั้ง &lt;code&gt;PasswordAuthentication no&lt;/code&gt; ใน &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chmod 600 .env&lt;/code&gt; และใส่ &lt;code&gt;.env&lt;/code&gt; ใน &lt;code&gt;.gitignore&lt;/code&gt; เสมอ — token หลุดขึ้น GitHub สาธารณะคือเคสที่เจอบ่อยมาก&lt;/li&gt;
&lt;li&gt;ติดตั้ง security update อัตโนมัติ: &lt;code&gt;apt install -y unattended-upgrades&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ถ้า token เคยหลุด ให้กด &lt;strong&gt;Reset Token&lt;/strong&gt; ทันที&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;แค่ Ubuntu + Node.js + systemd ก็ได้บอทที่ออนไลน์ 24/7, restart ตัวเองเมื่อ crash และดู log ได้ด้วย &lt;code&gt;journalctl&lt;/code&gt; โดยไม่ต้องติดตั้ง process manager เพิ่ม วิธีเดียวกันนี้ใช้กับบอท Python (&lt;code&gt;discord.py&lt;/code&gt;) ได้เลย แค่เปลี่ยน &lt;code&gt;ExecStart&lt;/code&gt; เป็น path ของ Python ใน virtualenv&lt;/p&gt;

&lt;p&gt;อ่านต่อ (ภาษาไทย): &lt;a href="https://vpskub.com/blog/vps-discord-bot" rel="noopener noreferrer"&gt;การเลือกสเปก VPS สำหรับ Discord Bot ตามขนาดบอท&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: ผมเป็นผู้ดูแล VPSKUB ที่ลิงก์ไว้ในบทความ แต่ขั้นตอนทั้งหมดใช้ได้กับ Ubuntu VPS ทุกเจ้า&lt;/em&gt;&lt;/p&gt;

</description>
      <category>discord</category>
      <category>node</category>
      <category>linux</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
