วิธีติดตั้ง Rocket.Chat ด้วย Docker Compose บน VPS
คู่มือติดตั้ง Rocket.Chat บน VPS ด้วย Docker Compose พร้อมวิธีตั้งค่า MongoDB replica set ที่จำเป็น การจัดการ TLS และการสำรองข้อมูลเพื่อแก้ปัญหาข้อผิดพลาดที่พบบ่อย
สิ่งที่คุณกำลังสร้าง
ระบบแชทส่วนตัวสำหรับทีมที่คุณเป็นเจ้าของโดยสมบูรณ์: Rocket.Chat ที่ทำงานบน VPS ของคุณผ่าน Docker Compose โดยมีการทำ TLS termination และข้อความทั้งหมดจะถูกจัดเก็บไว้ในฐานข้อมูล MongoDB ซึ่งคุณสามารถสำรองข้อมูลและย้ายได้ Rocket.Chat เป็นทางเลือกโอเพนซอร์สที่เสถียรสำหรับ Slack และ Teams รองรับการใช้งานแชนเนล, ข้อความส่วนตัว, เธรด, การแชร์ไฟล์ รวมถึงการสื่อสารด้วยเสียงและวิดีโอ ทั้งหมดนี้อยู่บนฮาร์ดแวร์ที่คุณเช่าและควบคุมเอง แอปพลิเคชันนี้เป็นคอนเทนเนอร์เดี่ยวที่สามารถเริ่มทำงานได้ภายในไม่กี่นาที ปัญหาที่อาจเกิดขึ้นส่วนใหญ่จะเกี่ยวข้องกับฐานข้อมูลที่อยู่ข้างกัน ดังนั้นเนื้อหาส่วนใหญ่ในคู่มือนี้จึงเน้นไปที่ MongoDB และโดยเฉพาะอย่างยิ่งข้อกำหนดหนึ่งที่มักทำให้ทุกคนประหลาดใจในครั้งแรก: Rocket.Chat ไม่สามารถทำงานร่วมกับ MongoDB แบบ standalone ได้ มันจำเป็นต้องใช้ replica set แม้ว่า "ชุด" ดังกล่าวจะมีเพียงโหนดเดียวก็ตาม
ข้อกำหนดเบื้องต้นและการคำนวณ RAM ที่ไม่มีใครบอกคุณ
จงเลือกขนาดเซิร์ฟเวอร์ตามความเป็นจริง เกณฑ์ขั้นต่ำที่ใช้งานได้จริงสำหรับทีมขนาดเล็กคือ 2 vCPU และ 4 GB RAM กระบวนการ Node.js ของ Rocket.Chat ต้องการ RAM ประมาณ 1 ถึง 1.5 GB โดยตัวมันเอง และ MongoDB ที่ใช้ WiredTiger cache จะจอง RAM ประมาณครึ่งหนึ่งของที่เหลืออยู่โดยค่าเริ่มต้น บน VPS ขนาด 2 GB ทั้งสองบริการจะทำงานได้ตอนบูตเครื่อง แต่จะชนกันทันทีที่มีทราฟฟิกจริงเข้ามา MongoDB จะขยายแคช, Node จะขยาย heap, kernel จะขาดแคลนหน่วยความจำ และตัวจัดการ out-of-memory killer จะสั่งปิดกระบวนการที่ใช้หน่วยความจำมากที่สุด ซึ่งมักจะเป็น mongod คอนเทนเนอร์จะแสดงข้อความ Killed, Docker จะสั่งรีสตาร์ท และคุณจะได้เซิร์ฟเวอร์แชทที่ล่มทุกสองสามนาทีภายใต้ภาระงานที่ควรจะรับมือได้สบาย 2 GB เหมาะสำหรับการทดสอบใช้งานกับคนสองคน แต่ไม่ใช่สำหรับเซิร์ฟเวอร์ของทีม เริ่มต้นที่ 4 GB และขยับเป็น 8 GB หากคุณคาดหวังผู้ใช้งานพร้อมกันหลายสิบคน, การวิดีโอคอล หรือประวัติการอัปโหลดที่เพิ่มขึ้นเรื่อยๆ
คุณต้องเตรียมสามสิ่งให้พร้อมก่อนเริ่มใช้งาน: ชื่อโดเมนที่มี A record ชี้ไปยัง IP สาธารณะของ VPS เนื่องจากฟีเจอร์แบบเรียลไทม์และไคลเอนต์มือถือของ Rocket.Chat ต้องการชื่อโฮสต์ที่เสถียร ไม่ใช่การระบุ IP โดยตรง, เปิดพอร์ต 80 และ 443 ทั้งบนไฟร์วอลล์ของเซิร์ฟเวอร์และไฟร์วอลล์เครือข่ายของผู้ให้บริการ ซึ่งมักจะเป็นส่วนควบคุมแยกต่างหากในแผงควบคุมส่วนใหญ่ และสุดท้ายคือ Ubuntu 24.04 KVM VPS ที่ติดตั้งใหม่พร้อมสิทธิ์ root หรือ sudo หากคุณยังตัดสินใจไม่ได้ว่าเซิร์ฟเวอร์แชทเป็นบริการแรกที่ควรติดตั้งหรือไม่ คู่มือสิ่งที่คุ้มค่าแก่การทำ self-host ในปี 2026 จะช่วยสรุปข้อดีข้อเสียให้คุณพิจารณา
ติดตั้ง Docker engine และ Compose plugin
ให้ใช้ apt repository ของ Docker โดยตรง แทนที่จะใช้แพ็กเกจ docker.io ที่มากับ Ubuntu หรือไฟล์ไบนารี Python แบบ standalone รุ่นเก่า docker-compose สำหรับ Compose เวอร์ชันปัจจุบันจะเป็น Docker plugin ซึ่งเรียกใช้งานผ่านคำสั่ง docker compose โดยใช้ช่องว่างแทนการใช้ขีดกลาง ส่วน docker-compose v1 รุ่นเก่าได้สิ้นสุดระยะเวลาสนับสนุนแล้ว และไม่สามารถจัดการ syntax ของ healthcheck และ dependency ที่ระบุไว้ด้านล่างได้อย่างถูกต้อง
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginตรวจสอบให้แน่ใจว่าติดตั้งทั้งสองส่วนเรียบร้อยแล้ว:
sudo docker version
sudo docker compose versionการที่ docker compose version แสดงผลลัพธ์ในลักษณะ Docker Compose version v2.x คือการตรวจสอบที่สำคัญ หากเกิดข้อผิดพลาดเป็น docker: 'compose' is not a docker command แสดงว่า plugin ไม่ได้ถูกติดตั้ง ซึ่งจะทำให้เกิดปัญหาที่หาสาเหตุได้ยากในภายหลัง ดังนั้นควรแก้ไขให้เรียบร้อยในขั้นตอนนี้
ไฟล์ compose: การตั้งค่า MongoDB เป็น single-node replica set
นี่คือส่วนที่ผู้คนมักทำผิดพลาด ดังนั้นโปรดอ่านอย่างละเอียด Rocket.Chat ใช้ change streams ของ MongoDB เพื่อส่งข้อความใหม่ไปยังไคลเอนต์ที่เชื่อมต่ออยู่แบบเรียลไทม์ ซึ่ง change streams จะใช้งานได้เฉพาะบน replica set เท่านั้น หากคุณชี้ Rocket.Chat ไปยัง MongoDB แบบ standalone ทั่วไป mongod ระบบจะเชื่อมต่อได้ แต่จะเปิด change stream ไม่สำเร็จและเกิดการ restart-loop ไปเรื่อยๆ วิธีแก้ไขนั้นไม่ซับซ้อน คุณเพียงแค่รันคอนเทนเนอร์ MongoDB ปกติหนึ่งตัว แต่ต้องเริ่มการทำงานด้วย --replSet จากนั้นจึงทำขั้นตอน initialize ให้เป็น replica set ที่มีสมาชิกตัวเดียว
สร้างไดเรกทอรีสำหรับทำงานและไฟล์ compose.yml:
services:
mongodb:
image: mongo:8.0
restart: always
command: ["mongod", "--replSet", "rs0", "--bind_ip_all", "--oplogSize", "128"]
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 10s
retries: 12
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:8.5.1
restart: always
depends_on:
mongodb:
condition: service_healthy
environment:
MONGO_URL: "mongodb://mongodb:27017/rocketchat?replicaSet=rs0"
MONGO_OPLOG_URL: "mongodb://mongodb:27017/local?replicaSet=rs0"
ROOT_URL: "https://chat.example.com"
PORT: "3000"
ports:
- "127.0.0.1:3000:3000"
volumes:
mongodb_data:
mongodb_config:ตัวเลือกบางอย่างในที่นี้ถูกกำหนดไว้อย่างตั้งใจ พอร์ตของ Rocket.Chat ถูกเผยแพร่ออกไปที่ 127.0.0.1:3000 ไม่ใช่ 0.0.0.0 ตัวแอปเองไม่มี TLS ดังนั้นควรให้เฉพาะ reverse proxy ที่อยู่บนเครื่องเดียวกันเท่านั้นที่เข้าถึงได้ การ bind พอร์ตนี้ไว้กับทุกอินเทอร์เฟซจะทำให้หน้าล็อกอินที่เป็น plaintext ปรากฏอยู่บนอินเทอร์เน็ตสาธารณะโดยตรง ส่วน MongoDB จะไม่ถูกเผยแพร่ออกไปยังโฮสต์เลย โดยจะเข้าถึงได้ผ่านเครือข่ายภายในของ Compose ภายใต้ชื่อ mongodb เท่านั้น ซึ่งเป็นชื่อโฮสต์เดียวกับที่ MONGO_URL ใช้งาน MONGO_URL จะระบุ ?replicaSet=rs0 หากละเว้นส่วนนี้ ไดรเวอร์จะมองว่าเซิร์ฟเวอร์เป็นแบบ standalone แม้ว่าจริงๆ แล้วจะเป็น replica set ก็ตาม ซึ่งจะทำให้การใช้ change streams ล้มเหลว MONGO_OPLOG_URL จะชี้ไปยังฐานข้อมูล local ซึ่งเป็นที่เก็บ oplog แม้ว่า Rocket.Chat รุ่นใหม่จะเน้นใช้ change streams เป็นหลัก แต่การตั้งค่านี้ก็ไม่มีผลเสียและช่วยให้โค้ดส่วนเดิมยังคงทำงานได้ตามปกติ depends_on ใช้ condition: service_healthy ดังนั้น Compose จะรอจนกว่า MongoDB จะตอบสนองต่อ ping ก่อนที่จะเริ่มรัน Rocket.Chat ซึ่งนี่คือหน้าที่ของ healthcheck
กำหนด version tag ที่แน่นอนให้กับ image ทั้ง 2 รายการ ได้แก่ mongo:8.0 และ Rocket.Chat release ที่ระบุชัดเจน เช่น 8.5.1 ในที่นี้ และห้ามใช้ :latest เพราะจะทำให้ docker pull ที่ไม่มีผู้ดูแลกลายเป็นการอัปเกรดโดยไม่ตั้งใจ ซึ่งไม่สามารถทำ migration ได้ ตรวจสอบ Rocket.Chat release ที่เสถียรล่าสุดและ version ของ MongoDB ที่รองรับก่อนกำหนด tag
Rocket.Chat เผยแพร่เอกสารข้อมูลที่เครื่องอ่านได้สำหรับแต่ละ release: curl -s https://releases.rocket.chat/8.5.1/info | jq '{compatibleMongoVersions, lts}' คืนค่า compatibleMongoVersions: ["8.0"] สำหรับ 8.5.1 ดังนั้น mongo:8.0 จึงเป็น engine เดียวที่รองรับ นอกจากนี้ยังมี flag lts เพื่อระบุว่า release นั้นเป็น build แบบ long-term support หรือไม่ ซึ่งเหมาะสำหรับการกำหนด tag ให้กับเซิร์ฟเวอร์ที่ไม่ต้องการดูแลบ่อย
ไม่ใช่ทุกโครงการจะเผยแพร่ image แบบมี version ในกรณีนี้ให้ย้ายการ pin ไปไว้ที่ source: การ self-hosting ตัวติดตามการออกกำลังกาย openGym หมายถึงการ checkout git tag ที่ระบุและ build จาก tag นั้น แทนการติดตาม branch ที่มีการเปลี่ยนแปลงอยู่เสมอ
การเริ่มต้นใช้งาน replica set
เริ่มการทำงานของ stack:
sudo docker compose up -dRocket.Chat จะเริ่มทำงานผิดพลาดทันทีและ Docker จะพยายามรีสตาร์ทบริการซ้ำๆ ซึ่งเป็นเรื่องปกติเนื่องจากยังไม่มี replica set อยู่ ให้สร้างขึ้นมาหนึ่งครั้งด้วยตนเองดังนี้:
sudo docker compose exec mongodb mongosh --eval 'rs.initiate({_id: "rs0", members: [{_id: 0, host: "mongodb:27017"}]})'ผลลัพธ์ที่ถูกต้องคือ { ok: 1 } ภายในเวลาไม่กี่วินาที โหนดเดี่ยวจะเลือกตัวเองเป็น primary ให้ตรวจสอบด้วยคำสั่ง:
sudo docker compose exec mongodb mongosh --quiet --eval 'rs.status().members[0].stateStr'คุณควรเห็น PRIMARY รายละเอียดที่สำคัญที่สุดในหน้านี้คืออาร์กิวเมนต์ host: "mongodb:27017" หากคุณรันคำสั่ง rs.initiate() เปล่าๆ โดยไม่มีรายการสมาชิก MongoDB จะประกาศชื่อ replica set โดยใช้ hostname ภายในของคอนเทนเนอร์ ซึ่งเป็นแฮชสุ่มอย่างเช่น a1b2c3d4e5f6 ซึ่ง Rocket.Chat ที่เชื่อมต่อจากคอนเทนเนอร์ของตัวเองจะไม่สามารถแก้ไขชื่อ (resolve) นั้นได้ ทำให้ไดรเวอร์ของ MongoDB ล้มเหลวในการค้นหา DNS และวนลูปบันทึก log MongoServerSelectionError: getaddrinfo ENOTFOUND a1b2c3d4e5f6 ตลอดไป ให้เริ่มต้นใช้งานด้วยชื่อบริการที่ชัดเจนซึ่งตรงกับ MONGO_URL ของคุณเสมอ
การบูตครั้งแรก: เฝ้าดูการเริ่มทำงาน
เมื่อชุดข้อมูลเป็น primary แล้ว การรีสตาร์ท Rocket.Chat ครั้งถัดไปจะเชื่อมต่อได้อย่างราบรื่นและเริ่มการย้ายข้อมูล (migration) สำหรับการใช้งานครั้งแรก ให้ติดตาม log ดังนี้:
sudo docker compose logs -f rocketchatบรรทัดที่คุณต้องรอคือแบนเนอร์การเริ่มทำงาน:
+--------------------------------------------+
SERVER RUNNING
Rocket.Chat Version: 8.5.1
NodeJS Version: 22.22.3 - x64
+--------------------------------------------+การบูตครั้งแรกจะใช้เวลานานเนื่องจากแอปพลิเคชันต้องดำเนินการย้ายข้อมูลในฐานข้อมูลและสร้างดัชนี ดังนั้นควรให้เวลาระบบสัก 1 หรือ 2 นาที ก่อนที่จะกังวล หาก log แสดงข้อความ MongoServerSelectionError: Server selection timed out after 30000 ms ซ้ำๆ พร้อมรายละเอียด topology ประเภท ReplicaSetNoPrimary แสดงว่า replica set ยังไม่ได้ถูกเริ่มต้น หากแสดงข้อความ getaddrinfo ENOTFOUND ซ้ำๆ พร้อมค่า hash แบบสุ่ม แสดงว่ามีการเริ่มต้นด้วยโฮสต์ที่ไม่ถูกต้อง ในกรณีใดกรณีหนึ่ง ให้ย้อนกลับไปทำขั้นตอนก่อนหน้า เมื่อคุณเห็นข้อความ SERVER RUNNING แสดงว่า Rocket.Chat กำลังฟังคำขออยู่ที่ 127.0.0.1:3000 และถึงเวลาที่จะต้องกำหนด hostname จริงและตั้งค่า TLS ไว้ด้านหน้าบริการแล้ว
การใช้งานผ่าน TLS
ห้ามเปิดใช้งาน Rocket.Chat ผ่าน HTTP แบบปกติโดยเด็ดขาด การล็อกอินผ่าน http:// เพียงครั้งเดียวจะทำให้รหัสผ่านผู้ดูแลระบบของคุณถูกส่งต่อไปยังผู้ที่ดักจับข้อมูลระหว่างทางได้ ให้ทำ TLS termination ที่ reverse proxy บนเครื่องเดียวกันแล้วส่งต่อคำขอไปยัง 127.0.0.1:3000 สิ่งที่ต้องคำนึงถึงมี 2 ประการ: proxy ต้องส่งต่อ WebSocket upgrade headers เนื่องจาก Rocket.Chat เป็นแอปพลิเคชันแบบเรียลไทม์ซึ่งจะทำงานไม่ได้หากไม่มีส่วนนี้ และ ROOT_URL ของคอนเทนเนอร์จะต้องตรงกับที่อยู่ HTTPS สาธารณะที่ผู้ใช้พิมพ์เข้าใช้งานอย่างถูกต้อง
เริ่มต้นด้วย nginx server block แบบ HTTP ปกติที่ทำหน้าที่ proxy ไปยังแอปและส่งต่อ upgrade headers บันทึกไฟล์เป็น /etc/nginx/sites-available/rocketchat, สร้าง symlink ไปยัง sites-enabled แล้วโหลดการตั้งค่าใหม่:
server {
listen 80;
server_name chat.example.com;
client_max_body_size 100M;
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-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}ให้เปิดใช้งานที่พอร์ต 80 ไปก่อน เนื่องจาก block ที่มี listen 443 ssl; แต่ไม่มีใบรับรองจะไม่ผ่านการตรวจสอบของ sudo nginx -t ให้โหลด nginx ใหม่ (sudo nginx -t && sudo systemctl reload nginx) จากนั้นจึงออกใบรับรอง วิธีที่สะดวกที่สุดบน Ubuntu คือ การใช้ใบรับรอง TLS จาก Let's Encrypt ด้วย Certbot และ nginx: certbot --nginx จะแก้ไข block ด้านบนให้โดยอัตโนมัติ โดยเพิ่ม listen 443 ssl;, บรรทัด ssl_certificate และการเปลี่ยนเส้นทางจาก 80 ไป 443 ให้อัตโนมัติ รวมถึงตั้งเวลาการต่ออายุใบรับรองให้คุณด้วย หากคุณใช้งานหลายคอนเทนเนอร์ผ่าน proxy เดียวกัน Traefik พร้อม TLS อัตโนมัติสำหรับแอป Docker หลายตัว จะเป็นทางเลือกที่เป็นระเบียบกว่า โดยให้เพิ่ม router และ service labels ลงในบริการ rocketchat แล้ว Traefik จะทำการร้องขอและต่ออายุใบรับรองให้คุณโดยไม่ต้องเขียน nginx block เลย ไม่ว่าจะใช้วิธีใด ให้ตั้งค่า ROOT_URL เป็น https://chat.example.com ใน compose.yml แล้วรัน sudo docker compose up -d อีกครั้งเพื่อให้คอนเทนเนอร์รับการเปลี่ยนแปลงดังกล่าว หากคุณต้องการให้เข้าถึงเซิร์ฟเวอร์ได้เฉพาะจากภายในเครือข่ายของคุณเองแทนที่จะเป็นอินเทอร์เน็ตสาธารณะ ให้วางระบบไว้หลัง WireGuard VPN ที่โฮสต์เองบน VPS และผูก proxy เข้ากับที่อยู่ของ tunnel แทน
วิซาร์ดการตั้งค่าสำหรับการใช้งานครั้งแรก
ไปที่ https://chat.example.com แล้ว Rocket.Chat จะนำคุณเข้าสู่ขั้นตอนวิซาร์ดสั้นๆ เริ่มจาก บัญชีผู้ดูแลระบบ (admin account) ซึ่งต้องระบุชื่อจริง ชื่อผู้ใช้ อีเมล และรหัสผ่านที่คาดเดายาก นี่เป็นบัญชีเดียวที่มีอยู่ในระบบ ดังนั้นห้ามทำข้อมูลส่วนนี้หาย ต่อมาคือ ข้อมูลองค์กรและเซิร์ฟเวอร์ (organisation and server info) ได้แก่ ชื่อองค์กร อุตสาหกรรม ขนาดขององค์กร ชื่อเว็บไซต์ และภาษาเริ่มต้น ข้อมูลส่วนนี้เป็นเพียงรายละเอียดทั่วไป ให้กรอกข้อมูลแล้วดำเนินการต่อ จากนั้นจะเป็นตัวเลือกที่สำคัญจริง ๆ คือ การลงทะเบียนพื้นที่ทำงาน (register this workspace) กับ Rocket.Chat Cloud หรือเลือกใช้แบบ standalone
การลงทะเบียนจะช่วยให้สามารถใช้งานการแจ้งเตือนแบบ push บนมือถือผ่านเกตเวย์ของ Rocket.Chat และใช้งาน add-on marketplace ได้ โดยแลกกับการที่เซิร์ฟเวอร์ต้องเชื่อมต่อกับ control-plane ของ Rocket.Chat Cloud ส่วนแบบ standalone จะทำให้เซิร์ฟเวอร์มีความเป็นส่วนตัวอย่างสมบูรณ์และไม่มีการพึ่งพาภายนอก แต่การแจ้งเตือนแบบ push บน iOS และ Android จะไม่ทำงาน เนื่องจาก Apple และ Google ไม่อนุญาตให้แอปที่สร้างขึ้นเองถือครองใบรับรองสำหรับการ push โดยแอปอย่างเป็นทางการจะต้องส่งข้อมูลผ่านเกตเวย์บนคลาวด์เท่านั้น ให้เลือก standalone หากความเป็นส่วนตัวคือเป้าหมายหลักและผู้ใช้ของคุณใช้งานผ่านเว็บแอปเป็นหลัก และให้เลือกการลงทะเบียนหากการแจ้งเตือนบนมือถือเป็นสิ่งที่จำเป็น คุณสามารถเปลี่ยนการตั้งค่านี้ได้ในภายหลังภายใต้เมนู Admin
จำกัดสิทธิ์การเข้าถึงก่อนเปิดให้ผู้อื่นใช้งาน
Rocket.Chat มาพร้อมกับการตั้งค่า open registration on โดยค่าเริ่มต้นของ Registration Form จะถูกตั้งไว้ที่ Public ดังนั้นใครก็ตามที่พบ URL ของคุณจะสามารถสร้างบัญชีได้ ซึ่งถือเป็นการเปิดช่องโหว่หากใช้งานบน hostname สาธารณะ ให้ไปที่ Admin → Settings → Accounts → Registration แล้วตั้งค่า Registration Form เป็น Disabled เพื่อให้คุณสร้างบัญชีด้วยตนเองหรือผ่านลิงก์คำเชิญ หรือตั้งเป็น Secret URL ในขณะเดียวกัน ให้ปิด Allow Anonymous Read และ Allow Anonymous Write เว้นแต่คุณต้องการให้ช่องแชทเป็นแบบสาธารณะที่อ่านได้อย่างเดียว หากการสร้างบัญชีทุกบัญชีด้วยตนเองดูเป็นภาระและนี่ไม่ใช่บริการเดียวที่ทีมของคุณใช้งาน ให้เชื่อมต่อการล็อกอิน OAuth ของ Rocket.Chat เข้ากับ เซิร์ฟเวอร์ Authentik SSO ที่คุณโฮสต์เอง แทน เพื่อให้การจัดการผู้ใช้งานเข้าและออกทำได้จากจุดเดียวแทนที่จะต้องทำแยกทีละแอป
นอกจากนี้ ให้ตัดสินใจเลือกตำแหน่งจัดเก็บไฟล์อัปโหลดด้วย ค่าเริ่มต้นของ File Upload คือ GridFS ซึ่งจะเก็บรูปภาพและไฟล์แนบทั้งหมดไว้ภายใน MongoDB โดยตรง วิธีนี้ทำได้ง่ายแต่หมายความว่าฐานข้อมูลของคุณและทุก mongodump ที่คุณทำจะมีขนาดใหญ่ขึ้นเรื่อยๆ ตามจำนวนภาพหน้าจอที่ผู้ใช้ส่งเข้ามา คุณสามารถเปลี่ยนการจัดเก็บไปยังระบบไฟล์ภายใน (local filesystem) หรือ S3-compatible bucket ได้ที่ Admin → Settings → File Upload พร้อมทั้งกำหนดขนาดไฟล์สูงสุดที่เหมาะสม สำหรับทีมขนาดเล็ก GridFS ถือว่าเพียงพอ แต่ควรทราบไว้ว่าไฟล์สำรองข้อมูลของคุณจะมีขนาดใหญ่ขึ้นตามกาลเวลา
การสำรองข้อมูลด้วย mongodump
ข้อมูลทั้งหมดของคุณอยู่ใน volume mongodb_data ห้ามคัดลอก volume ออกมาในขณะที่ฐานข้อมูลกำลังทำงานอยู่ ให้ใช้ mongodump เพื่อทำ dump ข้อมูลที่สอดคล้องกัน (consistent dump) และส่งข้อมูลไปยังไฟล์บนโฮสต์โดยตรง:
sudo docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > rocketchat-$(date +%F).archive.gzไฟล์ archive ที่บีบอัดด้วย gzip เพียงไฟล์เดียวนี้คือพื้นที่ทำงานทั้งหมดของคุณ ซึ่งประกอบด้วยผู้ใช้, ช่องทางสนทนา, ข้อความ, การตั้งค่า และไฟล์ต่างๆ หากคุณเก็บไฟล์อัปโหลดไว้บน GridFS หากคุณย้ายไฟล์อัปโหลดไปยังระบบไฟล์หรือ S3 ให้สำรองข้อมูลส่วนนั้นแยกต่างหาก การกู้คืนข้อมูลลงบน stack ใหม่ให้เริ่มจากการตั้งค่า replica set ก่อน จากนั้นจึงใช้คำสั่ง:
sudo docker compose exec -T mongodb mongorestore --archive --gzip --drop < rocketchat-2026-07-15.archive.gzให้คัดลอกไฟล์ archive ออกจากเซิร์ฟเวอร์ ไปยัง object storage, เซิร์ฟเวอร์อื่น หรือที่ใดก็ตามที่หาก VPS หลักเสียหาย ข้อมูลสำรองจะไม่สูญหายไปพร้อมกัน และให้ตั้งค่าการทำ dump ผ่าน cron เป็นประจำทุกคืน ข้อมูลสำรองที่คุณไม่เคยทดสอบกู้คืนถือเป็นเพียงความหวัง ไม่ใช่การสำรองข้อมูลที่แท้จริง ควรฝึกซ้อมการกู้คืนบน VPS ชั่วคราวอย่างน้อยหนึ่งครั้งเพื่อให้มั่นใจว่าใช้งานได้จริงก่อนถึงเวลาที่จำเป็นต้องใช้
การอัปเกรด: การระบุแท็ก, การอ่านบันทึกประจำรุ่น และการปฏิบัติตามตารางรองรับของ MongoDB
กฎ 2 ข้อช่วยให้การอัปเกรดเป็นเรื่องปกติและไม่เกิดปัญหา ประการแรก ให้อัปเกรด Rocket.Chat ทีละเวอร์ชันหลัก (major version) เท่านั้น ระบบจะทำการย้ายฐานข้อมูล (schema migration) เมื่อเริ่มทำงานและปฏิเสธที่จะข้ามเวอร์ชันหลักโดยเจตนา หากพยายามอัปเกรดจาก 6.x ไปยัง 8.x โดยตรง ระบบจะหยุดทำงานพร้อมข้อผิดพลาดในการย้ายข้อมูลแทนที่จะทำให้ข้อมูลเสียหาย ให้ปรับแท็กของ image ไปยังรุ่นล่าสุดของเวอร์ชันหลักถัดไป อ่านบันทึกประจำรุ่น (release notes) เพื่อดูการเปลี่ยนแปลงที่อาจส่งผลกระทบ (breaking changes) รันคำสั่ง docker compose up -d และเฝ้าดู log จนกว่าการย้ายข้อมูลจะเสร็จสิ้นก่อนดำเนินการขั้นตอนถัดไป ประการที่สอง ต้องปฏิบัติตามตารางการรองรับของ MongoDB Rocket.Chat แต่ละรุ่นรองรับ MongoDB เวอร์ชันที่กำหนดไว้ และ curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions จะระบุให้คุณทราบว่ารองรับเวอร์ชันใดบ้าง เมื่อคุณดำเนินการอัปเกรด MongoDB เช่น จาก 7.0 ไปเป็น 8.0 ให้ทำทีละเวอร์ชันหลักและตั้งค่า feature-compatibility version หลังจากอัปเกรดแต่ละครั้ง ใน MongoDB 8.0 คำสั่งดังกล่าวต้องใช้ confirm: true อย่างชัดเจน มิฉะนั้นระบบจะปฏิเสธการทำงานพร้อมข้อความแจ้งให้คุณรันคำสั่งใหม่โดยใส่แฟล็กยืนยัน:
sudo docker compose exec mongodb mongosh --eval 'db.adminCommand({setFeatureCompatibilityVersion: "8.0", confirm: true})'ให้ทำการ mongodump ก่อนการอัปเกรดส่วนประกอบใดๆ เสมอ นี่คือนโยบายการรับประกันความปลอดภัยทั้งหมดที่คุณต้องมี
รูปแบบความล้มเหลวและข้อความแจ้งเตือนที่ระบุ
Rocket.Chat เกิดการวนลูปเริ่มระบบใหม่ทันทีหลังจาก docker compose up และ docker compose logs rocketchat เต็มไปด้วย MongoServerSelectionError MongoDB กำลังทำงานอยู่แต่ไดรเวอร์ไม่สามารถเลือก primary ได้ โดยข้อความที่ปรากฏจะระบุความผิดพลาดที่คุณทำไว้ Server selection timed out after 30000 ms ที่มี topology type เป็น ReplicaSetNoPrimary หมายความว่าคุณยังไม่ได้รัน rs.initiate() ทำให้ชุดข้อมูลยังไม่มีการตั้งค่า getaddrinfo ENOTFOUND ตามด้วยแฮชแบบสุ่มหมายความว่าคุณเริ่มต้นระบบโดยไม่ได้ระบุ host: "mongodb:27017" ทำให้ MongoDB ประกาศชื่อโฮสต์ของคอนเทนเนอร์ที่ไม่สามารถแก้ไขได้ ให้ตรวจสอบด้วย sudo docker compose exec mongodb mongosh --eval 'rs.status()' หากแสดงข้อผิดพลาด MongoServerError: no replset config has been received ให้ทำการ initiate ชุดข้อมูล แต่หากแสดงสมาชิกที่มี name เป็นแฮชแบบสุ่ม ให้ทำการ re-initiate ใหม่โดยใช้ชื่อบริการ
หน้าเว็บ UI โหลดขึ้นมาได้แต่การล็อกอินหมุนค้างตลอดเวลาและไม่เสร็จสิ้น ให้เปิดคอนโซลของเบราว์เซอร์แล้วคุณจะพบ WebSocket connection to 'wss://chat.example.com/websocket' failed ปัญหานี้มักเกิดจาก ROOT_URL ไม่ตรงกัน หรือพร็อกซีไม่ได้ส่งต่อ upgrade headers ให้ตรวจสอบว่า ROOT_URL ตรงกับที่อยู่สาธารณะที่ถูกต้องรวมถึง https:// และตรวจสอบว่าบล็อก location ใน nginx ของคุณได้ตั้งค่า Upgrade และ Connection "upgrade" ด้วย proxy_http_version 1.1 แล้ว หากมีการเปลี่ยนแปลงให้รัน docker compose up -d ใหม่อีกครั้ง
คอนเทนเนอร์หยุดทำงานซ้ำๆ และ docker compose ps แสดงสถานะ Restarting docker compose logs ถูกตัดจบกลางคันและ sudo dmesg | tail แสดง Out of memory: Killed process 12345 (mongod) จาก oom-killer ซึ่งมี exit code เป็น 137 แสดงว่าเซิร์ฟเวอร์มี RAM ไม่เพียงพอ วิธีแก้ไขที่แท้จริงคือการอัปเกรด VPS ให้มีขนาดใหญ่ขึ้น โดยแนะนำขั้นต่ำที่ 4 GB สำหรับการแก้ปัญหาเฉพาะหน้า ให้เพิ่ม swap และจำกัดแคชของ MongoDB ด้วย --wiredTigerCacheSizeGB 1 ในไฟล์ command ของมัน อย่างไรก็ตาม swap เป็นเพียงการชะลอการเกิด OOM ในขณะที่มีโหลดใช้งานจริงเท่านั้น:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfiledocker compose up ล้มเหลวด้วยข้อความ Error response from daemon: driver failed programming external connectivity ... bind: address already in use มีบางอย่างใช้งานพอร์ต 3000 อยู่แล้ว ซึ่งมักเป็นคอนเทนเนอร์ Rocket.Chat ตัวเก่าที่หยุดทำงานไม่สมบูรณ์ หรือแอปพลิเคชันอื่น ให้ค้นหาด้วย sudo ss -ltnp | grep :3000 จากนั้นหยุดกระบวนการหรือคอนเทนเนอร์นั้น หรือเปลี่ยนฝั่งโฮสต์ของการทำ mapping เป็น 127.0.0.1:3001:3000 แล้วอัปเดต proxy_pass ของพร็อกซีให้ตรงกัน
FAQ
Rocket.Chat จำเป็นต้องใช้ MongoDB replica set จริงหรือ?
จำเป็น แม้จะเป็นเซิร์ฟเวอร์เดียวที่มีโหนดฐานข้อมูลเพียงโหนดเดียวก็ตาม Rocket.Chat ส่งข้อความแบบเรียลไทม์โดยใช้ MongoDB change streams ซึ่งฟีเจอร์นี้ใช้งานได้เฉพาะใน replica set เท่านั้น mongod แบบ standalone ไม่สามารถเปิดใช้งานได้ คุณไม่จำเป็นต้องใช้เครื่องหลายเครื่อง คุณสามารถรันคอนเทนเนอร์ MongoDB หนึ่งตัวที่เริ่มด้วย --replSet rs0 และกำหนดค่าให้เป็นเซตที่มีสมาชิกหนึ่งตัวด้วย rs.initiate() หากข้ามขั้นตอนนี้ไป ไดรเวอร์จะไม่พบ primary ทำให้ Rocket.Chat ติดลูปการรีสตาร์ทด้วย MongoServerSelectionError: Server selection timed out และไม่สามารถบูตระบบได้สำเร็จ
Rocket.Chat ที่โฮสต์เองต้องการ RAM เท่าไร?
ควรวางแผนไว้ที่ 4 GB เป็นขั้นต่ำสำหรับการใช้งานจริง และ 8 GB สำหรับทีมที่มีการใช้งานหนาแน่น กระบวนการ Node ของ Rocket.Chat ใช้ RAM ประมาณ 1 ถึง 1.5 GB และ MongoDB จะจอง RAM ประมาณครึ่งหนึ่งของที่เหลือไว้สำหรับ WiredTiger cache ดังนั้นบนเครื่องขนาด 2 GB ทั้งสองส่วนจะแย่งทรัพยากรกันจน out-of-memory killer สั่งยุติการทำงานของ mongod เมื่อมีโหลดการใช้งานจริง โดยจะแสดงข้อความ Killed ใน log และ exit code 137 ขนาด 2 GB จึงเพียงพอสำหรับการทดสอบซอฟต์แวร์กับผู้ใช้จำนวนน้อยเท่านั้น
จะนำ Rocket.Chat ไปไว้หลัง HTTPS ได้อย่างไร?
ให้รัน reverse proxy บน VPS เดียวกันเพื่อทำ TLS termination และส่งต่อคำขอไปยัง 127.0.0.1:3000 จากนั้นตั้งค่า ROOT_URL ของคอนเทนเนอร์ให้เป็น https:// สาธารณะของคุณ ตัว proxy ต้องส่งต่อ WebSocket upgrade headers มิฉะนั้นการล็อกอินจะค้าง การใช้ Certbot ร่วมกับ nginx เป็นวิธีที่ง่ายที่สุดสำหรับการตั้งค่าแอปเดียว ส่วน Traefik จะจัดการได้สะอาดตากว่าหากคุณรันหลายคอนเทนเนอร์หลัง proxy ตัวเดียวและต้องการการจัดการ certificate แบบอัตโนมัติ
จะสำรองข้อมูล Rocket.Chat ที่โฮสต์เองได้อย่างไร?
ให้ทำ database dump ที่มีความสอดคล้องของข้อมูลด้วย mongodump แทนการคัดลอก volume โดยตรงด้วยคำสั่ง docker compose exec -T mongodb mongodump --db rocketchat --archive --gzip > backup.archive.gz ไฟล์ archive ดังกล่าวจะประกอบด้วยข้อมูลผู้ใช้, ช่องแชท, ข้อความ, การตั้งค่า และไฟล์ที่อัปโหลดหากคุณเก็บไว้บน GridFS ให้คัดลอกไฟล์ออกจากเซิร์ฟเวอร์ ทำการสำรองข้อมูลอัตโนมัติทุกคืนด้วย cron และซ้อมทำ mongorestore บนเครื่องทดสอบเพื่อให้มั่นใจว่าการกู้คืนข้อมูลใช้งานได้จริง
จะอัปเกรด Rocket.Chat โดยไม่ทำให้ MongoDB เสียหายได้อย่างไร?
ให้อัปเกรด Rocket.Chat ทีละเวอร์ชันหลัก (major version) เนื่องจากระบบจะรันการย้ายข้อมูล (migration) ในขณะบูตและไม่อนุญาตให้ข้ามเวอร์ชันหลัก รวมถึงต้องอ่านบันทึกประจำรุ่น (release notes) ก่อนปรับเปลี่ยน image tag ที่ระบุไว้ ตรวจสอบว่าเวอร์ชันของ MongoDB ที่คุณต้องการรองรับกับรุ่นที่อัปเกรดหรือไม่ด้วย curl -s https://releases.rocket.chat/<version>/info | jq .compatibleMongoVersions และเมื่อคุณย้ายเวอร์ชัน MongoDB ให้ทำทีละเวอร์ชันหลักและตั้งค่า setFeatureCompatibilityVersion ด้วย confirm: true หลังจากอัปเกรดแต่ละขั้น และต้องทำ mongodump ไว้ก่อนเสมอ