📝
VPS

Strapi เป็น Headless CMS ที่เขียนด้วย Node.js ช่วยให้ทีมพัฒนาเก็บและจัดการเนื้อหาผ่าน REST API หรือ GraphQL ได้อย่างมีประสิทธิภาพ บทความนี้จะสอนวิธี deploy Strapi บน VPS Linux (Ubuntu 22.04 LTS) พร้อมการตั้งค่าที่เหมาะสำหรับ production

สรุปสั้น: Strapi คือ headless CMS ที่ใช้ Node.js ทำให้ frontend (React, Vue, Next.js) สามารถดึงเนื้อหาผ่าน API ได้ บทความนี้เราจะ install Node.js, สร้าง Strapi project, ตั้ง PM2 เพื่อ auto-restart, ใช้ Nginx เป็น reverse proxy, และ enable HTTPS ด้วย Let's Encrypt

Strapi คืออะไร และเหตุใดต้องใช้ Headless CMS

CMS แบบดั้งเดิม เช่น WordPress จะรวม backend (ที่จัดการเนื้อหา) และ frontend (ที่แสดงเนื้อหา) ไว้ด้วยกัน แต่ Headless CMS นั้นแยกออกมา:

ประโยชน์ของ Headless CMS:

สิ่งที่ต้องเตรียม

เคล็ดลับ: ถ้า VPS มี RAM แค่ 512 MB อาจใช้ได้ในช่วง development แต่ production ที่มี concurrent requests เยอะ ต้องขึ้นเป็น 1-2 GB ขึ้นไป หรือทำ optimization เช่น enable caching

ขั้นตอนที่ 1: ติดตั้ง Node.js

Strapi ต้องใช้ Node.js version 18 ขึ้นไป ให้ใช้ nvm (Node Version Manager) เพื่อจัดการ Node.js versions ได้ง่าย:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
source ~/.bashrc
nvm --version

ติดตั้ง Node.js LTS (version 20 หรือ 22):

nvm install 20
nvm use 20
node --version
npm --version

ตั้ง Node.js 20 เป็น default version:

nvm alias default 20

ขั้นตอนที่ 2: สร้าง Strapi Project

ใช้ create-strapi-app เพื่อสร้าง project ใหม่:

npx create-strapi-app@latest my-strapi-cms --quickstart

Strapi จะสร้าง project folder "my-strapi-cms" และติดตั้ง dependencies อัตโนมัติ เมื่อเสร็จจะมีไฟล์ดังนี้:

my-strapi-cms/
├── api/           # ไฟล์ plugin และ extensions
├── config/        # ไฟล์ configuration
├── database/      # database files (SQLite default)
├── public/        # static files ที่ serve ต่อ public
├── src/           # source code
├── package.json
└── .env           # environment variables

ขั้นตอนที่ 3: ตั้ง Environment Variables และ Database

SQLite vs Production Database: SQLite เหมาะ development ใช้ไฟล์ไม่ต้องติดตั้ง database server แต่ไม่เหมาะ production (lock issue, performance) PostgreSQL แนะนำ production ที่สุด stable, fast, scalable MySQL ใช้ได้ดี รองรับ MariaDB ด้วย

สำหรับบทความนี้จะใช้ PostgreSQL:

sudo apt update
sudo apt install postgresql postgresql-contrib -y
sudo systemctl start postgresql
sudo systemctl enable postgresql

สร้าง database user และ database:

sudo -u postgres psql
CREATE USER strapi WITH PASSWORD 'your_secure_password';
CREATE DATABASE strapi OWNER strapi;
\q

ข้อควรระวัง: อย่าใช้ password ที่เรียบง่าย ใช้ password ที่มี uppercase, lowercase, number, special character อย่างน้อย 16 ตัวอักษร และ เก็บไว้ในที่ปลอดภัย (password manager หรือ secret management)

แก้ไข .env file ใน Strapi project:

nano .env

เพิ่มตัวแปรสำหรับ production:

NODE_ENV=production
DATABASE_CLIENT=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=your_secure_password
JWT_SECRET=your_jwt_secret_here
API_TOKEN_SALT=your_api_token_salt_here
ADMIN_JWT_SECRET=your_admin_jwt_secret_here

สำหรับ JWT_SECRET, API_TOKEN_SALT, ADMIN_JWT_SECRET ให้ generate random string ด้วย:

openssl rand -base64 24

ขั้นตอนที่ 4: Build Strapi สำหรับ Production

ในโฟลเดอร์ project ให้รัน:

npm run build

คำสั่งนี้จะ compile TypeScript, optimize assets, และสร้าง dist folder สำหรับ production ใช้เวลา 2-5 นาทีขึ้นอยู่กับ VPS

ขั้นตอนที่ 5: ติดตั้ง และ ตั้ง PM2

PM2 คือ process manager ช่วยให้ Strapi restart อัตโนมัติ เมื่อ error หรือ VPS reboot:

npm install -g pm2

สร้าง ecosystem.config.js เพื่อกำหนด PM2 configuration:

cat > ecosystem.config.js << 'EOF'
module.exports = {
  apps: [{
    name: 'strapi',
    script: './node_modules/.bin/strapi',
    args: 'develop',
    env: {
      NODE_ENV: 'production',
      DATABASE_CLIENT: 'postgres',
      DATABASE_HOST: 'localhost',
      DATABASE_PORT: 5432,
      DATABASE_NAME: 'strapi',
      DATABASE_USERNAME: 'strapi',
      DATABASE_PASSWORD: 'your_secure_password'
    },
    watch: false,
    max_memory_restart: '1024M',
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    error_file: './logs/err.log',
    out_file: './logs/out.log',
    instances: 1
  }]
};
EOF

เริ่ม Strapi ด้วย PM2:

pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup

ตรวจสอบ Strapi ทำงาน:

pm2 logs strapi

ขั้นตอนที่ 6: ติดตั้ง และ ตั้ง Nginx

Nginx จะทำหน้าที่ reverse proxy ให้ Strapi (แทนการใช้ port 1337 โดยตรง) และ ทำให้ใช้ HTTPS ได้:

sudo apt install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx

สร้าง Nginx configuration file:

sudo nano /etc/nginx/sites-available/strapi

เพิ่มเนื้อหานี้:

upstream strapi {
  server 127.0.0.1:1337;
}

server {
  listen 80;
  server_name yourdomain.com;
  
  location / {
    proxy_pass http://strapi;
    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_redirect off;
  }
}

Enable site configuration:

sudo ln -s /etc/nginx/sites-available/strapi /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

เคล็ดลับ: ระบุ "yourdomain.com" ด้วย domain จริงของคุณ และระบุ hostname ตรง DNS records ให้ชี้ไปที่ IP ของ VPS

ขั้นตอนที่ 7: เปิดใช้ HTTPS ด้วย Certbot

ติดตั้ง Certbot และ Nginx plugin:

sudo apt install certbot python3-certbot-nginx -y

ขอ certificate จาก Let's Encrypt:

sudo certbot --nginx -d yourdomain.com

ตอบคำถาม แล้ว Certbot จะ update Nginx configuration และ enable HTTPS อัตโนมัติ

ตั้งให้ certificate auto-renew:

sudo systemctl start certbot.timer
sudo systemctl enable certbot.timer

ตรวจสอบว่า HTTPS ทำงาน:

curl -I https://yourdomain.com

ขั้นตอนที่ 8: ปลอดภัย และ Performance

ปลอดภัยด้าน Admin Panel: ตั้งรหัสผ่าน admin ที่ strong (16+ chars, special characters) ปิดการสมัครสมาชิก ใหม่ (Admin Panel → Settings → Users & Permissions → Roles) ใช้ API tokens สำหรับ programmatic access แล้ว set permissions อย่างละเอียด

ปลอดภัยด้าน Firewall:

sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Performance Tuning: เปิด caching ใน Nginx (set Cache-Control headers ใน Strapi) ใช้ CDN สำหรับ static assets และ images ตั้ง database connection pooling ใน Strapi config monitor memory/CPU ด้วย pm2 monit หรือ htop ปิด debug mode ใน production (NODE_ENV=production)

ข้อควรระวัง: อย่า expose .env file บน web server ตัวอักษรขึ้นต้นด้วยจุด (dot files) ไม่ควร serve ต่อ public ตั้งให้ Nginx และ application ignore files เหล่านี้

Content-Type Builder และการออกแบบ Schema เนื้อหา

หลังจาก Strapi ทำงานแล้ว งานหลักของทีมพัฒนาคือการออกแบบ "Content Types" ผ่านหน้า Content-Type Builder ใน admin panel ซึ่งเปรียบเสมือนการออกแบบตารางฐานข้อมูลแบบไม่ต้องเขียนโค้ด SQL เอง Strapi แบ่ง Content Type เป็นสองแบบหลัก คือ Collection Type สำหรับข้อมูลที่มีหลายรายการซ้ำกัน เช่น บทความบล็อก สินค้า หรือรีวิวลูกค้า และ Single Type สำหรับข้อมูลที่มีชุดเดียวตายตัว เช่น หน้า About Us หรือการตั้งค่า Homepage

แต่ละ Content Type ประกอบด้วย Field หลายประเภท เช่น Text, Rich Text, Number, Boolean, Date, Media (สำหรับอัปโหลดรูปภาพ/ไฟล์), Relation (เชื่อมโยงกับ Content Type อื่น เช่น บทความหนึ่งเชื่อมกับผู้เขียนหนึ่งคน), และ Component (กลุ่มฟิลด์ที่นำกลับมาใช้ซ้ำได้ เช่น SEO metadata ที่ใช้ในหลายหน้า) การออกแบบ Schema ที่ดีตั้งแต่ต้นจะช่วยลดงาน migrate ข้อมูลในภายหลัง เพราะการเปลี่ยนโครงสร้าง Content Type หลังจากมีข้อมูลจริงจำนวนมากแล้วอาจทำให้ข้อมูลเดิมเสียหายหรือต้อง manual migration

เคล็ดลับ: ก่อนสร้าง Content Type จริงบน production ให้ทดลองออกแบบบน environment development ก่อน และ export schema เป็นไฟล์ (Strapi เก็บ schema ไว้ใน src/api/*/content-types/*/schema.json) เพื่อ commit เข้า Git ทำให้ทีมสามารถ review การเปลี่ยนแปลง schema ผ่าน pull request ได้เหมือนโค้ดปกติ

อัปเดต Strapi เวอร์ชันใหม่อย่างปลอดภัย

Strapi มีการออก major version ใหม่เป็นระยะ ซึ่งบางครั้งมี breaking changes ที่กระทบ API หรือ Plugin ที่ใช้อยู่ ก่อนอัปเดตเวอร์ชันบน production ควรทำตามขั้นตอนนี้เสมอ: อันดับแรก สำรองข้อมูลฐานข้อมูล PostgreSQL ทั้งหมดด้วย pg_dump และสำรองโฟลเดอร์ media uploads แยกต่างหาก อันดับสอง ทดลองอัปเดตบน staging environment ที่มีข้อมูลจำลองใกล้เคียงกับ production ก่อนเสมอ อันดับสาม อ่าน migration guide อย่างเป็นทางการของ Strapi เพราะแต่ละ major version มักมีคำแนะนำเฉพาะเรื่องการย้าย Plugin หรือ API ที่เปลี่ยนแปลง

เมื่อพร้อมอัปเดตจริงบน production ให้ปิด maintenance mode หรือแจ้งผู้ใช้ล่วงหน้าถ้าเว็บไซต์มีผู้ใช้จำนวนมาก จากนั้นรันคำสั่ง npm install @strapi/strapi@latest ตามด้วย npm run build เพื่อ compile ใหม่ และรีสตาร์ท PM2 process ด้วย pm2 restart strapi หลังอัปเดตเสร็จ ให้ตรวจสอบ log ทันทีด้วย pm2 logs strapi --lines 100 เพื่อดูว่ามี error จาก Plugin ที่ไม่รองรับเวอร์ชันใหม่หรือไม่ หากพบปัญหาที่แก้ไม่ทัน สามารถ rollback กลับไปใช้ backup ฐานข้อมูลและ codebase เวอร์ชันเดิมได้ทันที ซึ่งเป็นเหตุผลที่การสำรองข้อมูลก่อนอัปเดตเป็นขั้นตอนที่ห้ามข้ามเด็ดขาด

สำรองข้อมูล Strapi อย่างสม่ำเสมอ

นอกจากการสำรองข้อมูลก่อนอัปเดตเวอร์ชันแล้ว ควรตั้งตารางสำรองข้อมูลอัตโนมัติเป็นประจำสำหรับ production เพราะข้อมูลเนื้อหาที่ทีมงานสร้างขึ้นทุกวันมีค่าและกู้คืนยากหากเซิร์ฟเวอร์มีปัญหา สิ่งที่ต้องสำรองมีสองส่วนหลัก คือฐานข้อมูล PostgreSQL ที่เก็บเนื้อหาทั้งหมด และโฟลเดอร์ media uploads ที่เก็บไฟล์รูปภาพและเอกสารที่ผู้ใช้อัปโหลด การสำรองฐานข้อมูลทำได้ด้วยคำสั่ง pg_dump -U strapi strapi > backup-$(date +%Y%m%d).sql ซึ่งควรตั้งเป็น cron job รันทุกคืน แล้วอัปโหลดไฟล์ backup ไปเก็บไว้นอกเซิร์ฟเวอร์ เช่น cloud storage หรือ VPS อีกเครื่องหนึ่ง เพื่อป้องกันกรณีเซิร์ฟเวอร์หลักเสียหายทั้งหมด

สำหรับโฟลเดอร์ media uploads สามารถใช้ rsync หรือ tar สำรองเป็นระยะ หรือถ้าต้องการความน่าเชื่อถือสูงขึ้น ให้พิจารณาย้ายการเก็บไฟล์ media จาก local disk ไปใช้ S3-compatible object storage แทน ซึ่ง Strapi รองรับผ่าน plugin upload provider ทำให้ไฟล์ media ไม่ผูกติดกับเซิร์ฟเวอร์เครื่องเดียวอีกต่อไป และยังช่วยลดภาระ disk I/O บน VPS หลักได้ด้วย

สรุป

ขั้นตอนหลักของการ deploy Strapi บน VPS: ติดตั้ง Node.js (version 20 หรือ 22) สร้าง Strapi project ด้วย create-strapi-app ตั้ง database (PostgreSQL แนะนำ) และ environment variables build Strapi สำหรับ production ใช้ PM2 เพื่อ manage process และ auto-restart ตั้ง Nginx เป็น reverse proxy เปิด HTTPS ด้วย Let's Encrypt ตั้ง security (firewall, strong passwords, API tokens)

เมื่อจบขั้นตอนนี้ Strapi admin panel จะเข้าถึงได้ที่ https://yourdomain.com/admin และ API endpoints สามารถใช้งานจาก frontend applications ได้

คำถามที่พบบ่อย (FAQ)

PM2 ช่วยอะไรในการ deploy Strapi?

PM2 คือ process manager ที่ช่วยให้ Strapi process รันอยู่เสมอ เมื่อ error หรือ VPS restart ก็ auto-restart Strapi ขึ้นมาใหม่ โดยไม่ต้องเข้า terminal และรัน manual

ใช้ SQLite ในการ production ได้ไหม?

SQLite ใช้ได้กับ development แต่ production ไม่แนะนำ เพราะ SQLite lock database เวลา concurrent writes ทำให้ performance ตก แนะนำใช้ PostgreSQL หรือ MySQL แทน

Strapi port 1337 มีปลอดภัยไหม ถ้าเปิดให้ public?

ไม่ปลอดภัย ควรใช้ Nginx เป็น reverse proxy ให้ hide port 1337 ที่ระดับ localhost และเปิดแค่ port 80/443 (HTTP/HTTPS) ต่อ public ด้วย firewall rules

ถ้า certificate Let's Encrypt หมดอายุ จะเกิดอะไรขึ้น?

Certbot ตั้งให้ auto-renew อัตโนมัติ 30 วันก่อนหมดอายุ หากใช้ systemd timer ไม่ต้องทำอะไรเพิ่มเติม เพียงตรวจสอบว่า certbot.timer ทำงาน

เริ่มต้นใช้งาน VPS AsiaGB วันนี้

VPS AsiaGB ใช้ SSD Storage ทุก Plan เลือก Datacenter ไทยหรือสิงคโปร์ได้ พร้อม Root Access เต็มรูปแบบ เริ่มต้น 500 บาท/เดือน (Linux) พร้อมทีมซัพพอร์ตภาษาไทย

ดูแพ็กเกจ VPS