การดูแลระบบ › Backup และการอัปเกรด
เอกสาร/การดูแลระบบ/Backup และการอัปเกรด

Backup และการอัปเกรด

หน้านี้สอนอะไร

ต้องสำรองอะไร กู้คืนอย่างไร และอัปเกรด Easy CMS อย่างปลอดภัย

ควรอ่านก่อน: Migration และการ deploy

Easy CMS เก็บข้อมูลไว้สองที่: ฐานข้อมูล (เอกสาร, ผู้ใช้, versions, งานที่ตั้งเวลา, webhook ที่รอส่ง และตาราง migrations) และ ไฟล์อัปโหลด (upload.dir บนเครื่อง หรือ bucket S3) ต้อง backup ทั้งสองอย่าง Easy CMS ไม่ได้ backup ให้

ต้อง backup อะไรบ้าง

อะไรอยู่ที่ไหนบ่อยแค่ไหน
ฐานข้อมูลไฟล์ SQLite หรือฐานข้อมูล Postgresทุกวัน และก่อนทุกครั้งที่ deploy แล้วมี migration
ไฟล์อัปโหลดuploads/ (หรือ upload.dir) หรือ bucket S3ทุกวัน ถ้าใช้ S3 ให้เปิด bucket versioning
EASY_CMS_SECRETที่ตั้งค่า secret ของ hostครั้งเดียว เก็บไว้ใน password manager
easy-cms/migrationsGitมีอยู่แล้วเมื่อ commit

ถ้า EASY_CMS_SECRET หาย ข้อมูลไม่หาย เพราะใช้เซ็น session และลิงก์ preview ไม่ได้ใช้กับรหัสผ่าน การตั้งค่าใหม่จะทำให้ทุกคนหลุดออกจากระบบและลิงก์ preview เดิมใช้ไม่ได้

จากหน้า admin

ตั้งค่า → Backups: รอบที่ตั้งไว้ ปุ่ม Backup ตอนนี้ และรายการ backup พร้อมปุ่มดาวน์โหลดตั้งค่า → Backups: รอบที่ตั้งไว้ ปุ่ม Backup ตอนนี้ และรายการ backup พร้อมปุ่มดาวน์โหลด

admin เปิด ตั้งค่า → Backups ในหน้า admin ได้ มีปุ่ม Backup ตอนนี้ รายการ backup พร้อมบอกว่าใครทำ ปุ่ม ดาวน์โหลด และ ลบ ส่วนรอบอัตโนมัติและจำนวนที่เก็บตั้งใน config:

import { sqlite } from '@easy-cms/db-sqlite'
 
backups: {
  every: 'day',          // หรือ 'week' ไม่ใส่ = กดทำเองเท่านั้น
  at: '03:00',           // เวลาของ server
  keep: 7,               // ชุดที่เก่ากว่านี้จะถูกลบ
  // dir: 'backups',     // ค่าเริ่มต้น ไม่เปิดเป็น URL สาธารณะ
  // storage: s3Storage({ bucket: 'my-private-backups' }), // แทนดิสก์ของ server
  // sqlite,             // เฉพาะ Postgres ดูด้านล่าง
},
  • backup แต่ละชุดเป็นไฟล์ SQLite บีบอัดไฟล์เดียว (<ชื่อเว็บ>-YYYY-MM-DD-HHmm.db.gz) ของทั้งฐานข้อมูล: เอกสาร ผู้ใช้ เวอร์ชัน การตั้งค่า SQLite คัดลอกตัวเองได้ ส่วน Postgres ถูกคัดลอกลงไฟล์ SQLite จึงต้องส่ง sqlite จาก @easy-cms/db-sqlite เป็น backups.sqlite (ติดตั้งแพ็กเกจนั้นด้วย) ถ้าฐานข้อมูล Postgres ใหญ่ ควรใช้ backup ของผู้ให้บริการ หรือ pg_dump ควบคู่ไปด้วย
  • ไม่รวมไฟล์ที่อัปโหลด: backup โฟลเดอร์ uploads แยก หรือเปิด versioning ของ S3 bucket
  • เก็บที่ไหน: ค่าเริ่มต้นคือ backups/ บนดิสก์ของ server ซึ่งหายไปพร้อม server (และบน serverless หายทุกครั้งที่ deploy) ตั้ง backups.storage เป็น bucket ส่วนตัว หรือดาวน์โหลดเก็บไว้ ห้ามใช้โฟลเดอร์ uploads หรือ bucket สาธารณะ เพราะ backup มี hash ของรหัสผ่านและ API key
  • backup ตามรอบ ทำงานพร้อมงานที่ตั้งเวลาไว้: ทุกนาทีบน server ที่ทำงานต่อเนื่อง หรือจาก cron ที่เรียก <api>/jobs/run ทำทีละชุด ชุดที่ค้างเพราะ process หยุดกลางทางจะถูกทำต่อในรอบถัดไป แดชบอร์ดจะเตือน admin เมื่อ backup ตามรอบครั้งล่าสุดไม่สำเร็จ หรือไม่มีชุดที่สำเร็จนานเกินสองรอบ
  • การดาวน์โหลด ผ่าน server เฉพาะ admin และรายการบอกว่าใครดาวน์โหลดครั้งล่าสุด เก็บไฟล์ที่ดาวน์โหลดให้ปลอดภัยเท่ากับฐานข้อมูล
  • อัปเกรดเป็น Easy CMS 0.32 จะเพิ่มตาราง database-backups ต้องสร้าง migration (npx easy-cms migrate:create backups)

กู้คืนจาก backup ของหน้า admin

การกู้คืนทำบน server ไม่ใช่ในหน้า admin แตกไฟล์ก่อน:

gunzip my-site-2026-10-04-0300.db.gz
  • SQLite: หยุด server แทนที่ cms.db ด้วยไฟล์ที่แตกแล้ว (ลบ cms.db-wal และ cms.db-shm ถ้ามี) แล้วเริ่ม server
  • Postgres: คัดลอกไฟล์เข้าฐานข้อมูลว่างด้วย easy-cms copy ตามการย้ายจาก SQLite ไป Postgres โดยใช้ config ที่ db เป็น sqlite({ url: 'file:./my-site-2026-10-04-0300.db' }) เป็นต้นทาง

SQLite

ฐานข้อมูลทำงานในโหมด WAL การคัดลอก cms.db ขณะ server ทำงานอาจได้ไฟล์ที่เสีย ให้ใช้ easy-cms backup แทน คำสั่งนี้อ่าน config ของโปรเจกต์แล้วเขียนสำเนาที่สมบูรณ์ได้ขณะ CMS ทำงานอยู่

npm
npx easy-cms backup backups/cms-$(date +%F).db
pnpm
pnpm exec easy-cms backup backups/cms-$(date +%F).db
yarn
yarn easy-cms backup backups/cms-$(date +%F).db
bun
bunx easy-cms backup backups/cms-$(date +%F).db

คำสั่ง sqlite3 ก็ทำได้เหมือนกัน: sqlite3 cms.db ".backup 'backups/cms.db'"

กู้คืน: หยุด server แทนที่ cms.db ด้วยไฟล์ backup แล้วลบ cms.db-wal และ cms.db-shm ถ้ามี จากนั้นเริ่ม server

Postgres

pg_dump --format=custom --file=cms-$(date +%F).dump "$DATABASE_URL"

ถ้าฐานข้อมูลใช้ร่วมกับแอปอื่น ให้ dump เฉพาะตารางของ Easy CMS ด้วย prefix (tablePrefix ค่าเริ่มต้น ecms_): pg_dump -t 'ecms_*' … ส่วน Postgres แบบ managed (Neon, Supabase, RDS…) มักมี point-in-time recovery ให้เปิดไว้ด้วย

กู้คืน: หยุด server แล้วรัน

pg_restore --clean --if-exists --no-owner --dbname="$DATABASE_URL" cms-2026-10-01.dump

หลังกู้คืน

backup มีตาราง migrations อยู่ด้วย ฐานข้อมูลจึงอยู่ที่ schema ของวันที่ backup ให้เริ่มแอปเวอร์ชันที่ตรงกับตอนนั้น หรือ deploy เวอร์ชันปัจจุบันแล้วรัน easy-cms migrate เพื่อเพิ่ม migration ที่สร้างหลังจากนั้น server ในโหมด production จะไม่ยอมเริ่มถ้าไม่ตรงกัน จึงเห็นปัญหาทันทีแทนที่ข้อมูลจะเสีย

ลองกู้คืนดู เป็นระยะ: กู้คืนลงฐานข้อมูลทดลอง เริ่มแอปกับฐานข้อมูลนั้น แล้วเปิดหน้า admin backup ที่ไม่เคยลองกู้คืนก็ยังไม่รู้ว่าใช้ได้จริง

อัปเกรด Easy CMS

แพ็กเกจ @easy-cms/*, easy-cms และ create-easy-cms ใช้เลขเวอร์ชันเดียวกัน ให้อัปเกรดพร้อมกันทั้งหมด

  1. อ่าน changelog ของเวอร์ชันที่อยู่ระหว่างทาง (packages/core/CHANGELOG.md บน GitHub หรือ npm view @easy-cms/core --json)
  2. อัปเกรดทุกแพ็กเกจเป็นเวอร์ชันเดียวกัน:
npm
npm install @easy-cms/core@latest @easy-cms/nuxt@latest @easy-cms/db-sqlite@latest easy-cms@latest
pnpm
pnpm add @easy-cms/core@latest @easy-cms/nuxt@latest @easy-cms/db-sqlite@latest easy-cms@latest
yarn
yarn add @easy-cms/core@latest @easy-cms/nuxt@latest @easy-cms/db-sqlite@latest easy-cms@latest
bun
bun add @easy-cms/core@latest @easy-cms/nuxt@latest @easy-cms/db-sqlite@latest easy-cms@latest
  1. รัน npx easy-cms migrate:create upgrade บางเวอร์ชันเพิ่มตารางภายใน (0.7 เพิ่ม webhook-deliveries) ถ้ามีจะได้ migration ให้ตรวจและ commit ถ้าไม่มี migration นี้ production จะไม่ยอมเริ่ม
  2. ลองกับสำเนาข้อมูล production (backup ที่กู้คืนแล้ว) ก่อน deploy
  3. deploy ตามปกติ: backup, easy-cms migrate, เริ่มเวอร์ชันใหม่

ย้อนกลับ: migration เดินหน้าอย่างเดียว ถ้าจะกลับไปเวอร์ชันก่อน ให้กู้คืน backup ที่ทำไว้ก่อน deploy แล้ว deploy แอปเวอร์ชันก่อนหน้า

เวอร์ชันและการสนับสนุน

Easy CMS ใช้ semantic versioning ตามกติกาปกติของเวอร์ชันก่อน 1.0:

  • ก่อน 1.0 (ตอนนี้): minor release (0.8 → 0.9) อาจเปลี่ยน API, config หรือรูปแบบคำตอบของ REST changelog จะบอกว่าเปลี่ยนอะไรและต้องแก้อย่างไร ส่วน patch release (0.9.0 → 0.9.1) แก้บั๊กอย่างเดียว
  • ตั้งแต่ 1.0: breaking change เฉพาะใน major release พร้อมคู่มืออัปเกรดใน changelog API ที่เลิกใช้จะยังทำงานพร้อมคำเตือนจนถึง major ถัดไป
  • การแก้ช่องโหว่ ออกให้ minor release ล่าสุด (และตั้งแต่ 1.0 ให้ major ก่อนหน้าด้วยเป็นเวลาหกเดือน) ดูนโยบายความปลอดภัย

ขั้นต่อไป