รันแอป Node.js ด้วย PM2 และ Nginx Reverse Proxy
คำตอบสั้น ๆ: ติดตั้ง Node.js LTS รันแอปด้วย PM2 ให้เริ่มใหม่เองเมื่อแอปล่มหรือรีบูตเครื่อง และใช้ Nginx เป็น Reverse Proxy รับโดเมนจริงบนพอร์ต 80 และ 443
คู่มือนี้อธิบาย Nginx Reverse Proxy ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
แอป Node.js เช่น Express, Next.js หรือ NestJS ปกติจะฟังอยู่ที่พอร์ตสูงอย่าง 3000 การรันด้วย node app.js ตรง ๆ มีข้อเสียคือแอปจะหยุดเมื่อปิด SSH หรือเกิด Error และไม่เปิดเองหลังรีบูตเครื่อง PM2 เป็น Process Manager ที่แก้ปัญหาเหล่านี้ ส่วน Nginx ทำหน้าที่ Reverse Proxy รับคำขอจากโดเมนจริงที่พอร์ต 80 และ 443 แล้วส่งต่อให้แอป รวมถึงจัดการ SSL ได้
คู่มือนี้ใช้ Ubuntu 22.04 หรือ 24.04 เป็นหลัก และให้คำสั่งสำหรับ AlmaLinux หรือ Rocky Linux ในจุดที่ต่างกัน
สิ่งที่ต้องเตรียม (Nginx Reverse Proxy)
- ผู้ใช้ทั่วไปที่มีสิทธิ์
sudo ไม่ควรรันแอปด้วย root (ดู สร้างผู้ใช้ใหม่และให้สิทธิ์ sudo บน Linux) - Nginx ติดตั้งแล้ว (
sudo apt install -y nginx หรือ sudo dnf install -y nginx) - โดเมนที่ชี้ A Record มายังเซิร์ฟเวอร์ และพอร์ต 80/443 เปิดแล้ว
ขั้นตอนที่ 1: ติดตั้ง Node.js เวอร์ชัน LTS (Nginx Reverse Proxy)
แพ็กเกจ nodejs ที่มากับ Ubuntu มักเป็นเวอร์ชันเก่า แนะนำให้ติดตั้งจาก Repository ของ NodeSource ตัวอย่างนี้ใช้ Node.js 24 ซึ่งเป็น LTS ในขณะที่เขียน ตรวจเวอร์ชัน LTS ล่าสุดได้ที่ nodejs.org แล้วเปลี่ยนตัวเลขในคำสั่งให้ตรง
Ubuntu
curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt-get install -y nodejs
AlmaLinux และ Rocky Linux
curl -fsSL https://rpm.nodesource.com/setup_24.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo dnf install -y nodejs
ตรวจสอบเวอร์ชัน
node -v
npm -v
ขั้นตอนที่ 2: เตรียมแอปตัวอย่าง (Nginx Reverse Proxy)
หากมีแอปอยู่แล้วให้ข้ามไปขั้นตอนที่ 3 ได้ สิ่งสำคัญคือแอปควรฟังที่ 127.0.0.1 ไม่ใช่ทุก Interface เพื่อให้เข้าถึงได้ผ่าน Nginx เท่านั้น
mkdir -p ~/apps/myapp && cd ~/apps/myapp
nano app.js
const http = require('http');
const PORT = process.env.PORT || 3000;
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end('Hello from Node.js\n');
}).listen(PORT, '127.0.0.1', () => {
console.log(`Listening on 127.0.0.1:${PORT}`);
});
ขั้นตอนที่ 3: ติดตั้ง PM2 และรันแอป
sudo npm install -g pm2
pm2 start app.js --name myapp
pm2 status
ตาราง pm2 status ควรแสดงแอปชื่อ myapp สถานะ online สำหรับแอปที่เริ่มด้วย npm start ใช้ pm2 start npm --name myapp -- start แทน
ตั้งให้ PM2 เปิดเองเมื่อบูตเครื่อง โดยรันคำสั่งนี้ด้วยผู้ใช้ที่รันแอป (ไม่ใช่ root)
pm2 startup systemd
PM2 จะพิมพ์คำสั่งที่ขึ้นต้นด้วย sudo env PATH=... ออกมาหนึ่งบรรทัด ให้คัดลอกบรรทัดนั้นไปรันตามที่แสดง จากนั้นบันทึกรายการแอปที่กำลังรันอยู่
pm2 save
ทุกครั้งที่เพิ่มหรือลบแอปใน PM2 ต้องรัน pm2 save อีกครั้ง ไม่เช่นนั้นหลังรีบูตจะได้รายการเดิม
คำสั่งที่ใช้บ่อย
| คำสั่ง | หน้าที่ |
|---|
pm2 logs myapp | ดู Log ของแอป |
pm2 restart myapp | รีสตาร์ตแอปหลังอัปเดตโค้ด |
pm2 reload myapp | รีโหลดแบบไม่ขาดช่วง (ใช้ได้กับโหมด cluster) |
pm2 monit | ดู CPU และ RAM ของแต่ละแอปแบบเรียลไทม์ |
ขั้นตอนที่ 4: ตั้งค่า Nginx เป็น Reverse Proxy
สร้างไฟล์ตั้งค่า บน Ubuntu ใช้ /etc/nginx/sites-available/myapp บน AlmaLinux หรือ Rocky Linux ใช้ /etc/nginx/conf.d/myapp.conf
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 60s;
}
}
บรรทัด Upgrade และ Connection ทำให้ WebSocket (เช่น Socket.IO) ผ่าน Proxy ได้ ส่วน X-Forwarded-* ทำให้แอปรู้ IP จริงของผู้ใช้และรู้ว่าเข้ามาทาง HTTPS หรือไม่ หากใช้ Express ให้ตั้ง app.set('trust proxy', 1) ในแอปด้วย
บน Ubuntu เปิดใช้งานไฟล์ด้วย
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
จากนั้นทดสอบและโหลดค่าใหม่ (ทุก Distro)
sudo nginx -t
sudo systemctl reload nginx
บน AlmaLinux และ Rocky Linux ที่เปิด SELinux ไว้ Nginx จะเชื่อมต่อไปยังพอร์ตภายในไม่ได้จนกว่าจะอนุญาต
sudo setsebool -P httpd_can_network_connect 1
เมื่อ Proxy ทำงานแล้ว ติดตั้ง HTTPS ได้ตามคู่มือ ติดตั้ง SSL ฟรีจาก Let's Encrypt ด้วย Certbot บน Nginx
ตรวจสอบผลลัพธ์
curl http://127.0.0.1:3000 บนเซิร์ฟเวอร์ต้องได้ Hello from Node.jscurl -I http://app.example.com จากเครื่องอื่นต้องได้ 200 OKsudo ss -tlnp | grep 3000 ต้องเห็น 127.0.0.1:3000 แปลว่าพอร์ตแอปไม่เปิดสู่ภายนอก- สั่ง
sudo reboot แล้ว Login กลับมาดู pm2 status ต้องเห็นแอปเป็น online
ปัญหาที่พบบ่อยเกี่ยวกับ Nginx Reverse Proxy
502 Bad Gateway
Nginx ต่อแอปไม่ได้ ตรวจว่าแอปยัง online ใน pm2 status และพอร์ตใน proxy_pass ตรงกับพอร์ตที่แอปฟังจริง ดูสาเหตุได้จาก pm2 logs myapp และ /var/log/nginx/error.log บน AlmaLinux หรือ Rocky Linux หาก Log มีคำว่า Permission denied ขณะ connect มักเป็นเรื่อง SELinux ตามขั้นตอนที่ 4
แอปไม่กลับมาหลังรีบูต
ลืมรันคำสั่งที่ pm2 startup พิมพ์ออกมา หรือลืม pm2 save อีกกรณีคือรัน pm2 startup ด้วย root แต่รันแอปด้วยผู้ใช้อื่น ให้ลบด้วย pm2 unstartup systemd แล้วทำขั้นตอนที่ 3 ใหม่ด้วยผู้ใช้ที่ถูกต้อง
แอปรีสตาร์ตวนไม่หยุด
ในคอลัมน์ ↺ ของ pm2 status ตัวเลขจะเพิ่มขึ้นเรื่อย ๆ แปลว่าแอป Crash ทันทีหลังเปิด ดูสาเหตุจาก pm2 logs myapp --lines 100 ที่พบบ่อยคือขาด Environment Variable หรือยังไม่ได้รัน npm install
Log ของ PM2 กินพื้นที่ดิสก์
Log เก็บอยู่ที่ ~/.pm2/logs และไม่ถูกหมุนเวียนเอง ติดตั้งโมดูลหมุน Log ด้วย pm2 install pm2-logrotate
หากทำตามขั้นตอนแล้วยังติดปัญหา สามารถติดต่อทีมงาน Support ของ THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/ โดยแจ้งชื่อเซิร์ฟเวอร์ ระบบปฏิบัติการ ขั้นตอนที่ทำไปแล้ว และข้อความ Error ที่พบ เพื่อให้ตรวจสอบได้รวดเร็วขึ้น
สรุปขั้นตอน Nginx Reverse Proxy
ทบทวน Nginx Reverse Proxy ทั้งหมดตามลำดับ ก่อนนำไปใช้กับระบบจริง
- ติดตั้ง Node.js เวอร์ชัน LTS (Nginx Reverse Proxy)
- เตรียมแอปตัวอย่าง (Nginx Reverse Proxy)
- ติดตั้ง PM2 และรันแอป
- ตั้งค่า Nginx เป็น Reverse Proxy
เมื่อทำครบทุกข้อแล้ว Nginx Reverse Proxy จะพร้อมใช้งาน หากผลลัพธ์ไม่เป็นไปตามที่คาด ให้ย้อนกลับไปดูหัวข้อปัญหาที่พบบ่อยด้านบน ซึ่งรวบรวมกรณีที่พบจริงจากการใช้งาน Nginx Reverse Proxy ไว้แล้ว
อ่านเพิ่มเติมเกี่ยวกับ Nginx Reverse Proxy