diff --git a/TENANT_PROVISIONING_POSTMORTEM_CHECKLIST.md b/TENANT_PROVISIONING_POSTMORTEM_CHECKLIST.md new file mode 100644 index 0000000..dda90ab --- /dev/null +++ b/TENANT_PROVISIONING_POSTMORTEM_CHECKLIST.md @@ -0,0 +1,114 @@ +# สรุปปัญหา ข้อผิดพลาด และ Checklist การสร้าง Tenant / Subdomain ใหม่ +(Tenant Provisioning Post-Mortem & Standard Operating Procedure) + +บันทึกข้อผิดพลาดจากการสร้าง Showcase Subdomains (`wellness`, `fashion`, `beauty`, `moto`) บน `kittisak.com` เมื่อวันที่ 24 กันยายน 2026 เพื่อใช้เป็น Checklist ป้องกันการทำผิดพลาดซ้ำในอนาคต + +--- + +## 1. ปัญหาและข้อผิดพลาดที่เกิดขึ้น (What Went Wrong) + +### ข้อผิดพลาดหลักที่ 1: ลืมรันคำสั่ง Seed ฐานข้อมูล (ตกหล่นขั้นตอนที่ 8 ของ DEPLOYMENT_GUIDE.md) +* **สิ่งที่เกิดขึ้น:** หลังจากสร้างฐานข้อมูล PostgreSQL ใหม่ทั้ง 4 ตัว (`wellness_db`, `fashion_db`, `beauty_db`, `moto_db`) ได้ทำการรัน `bunx prisma db push` เพื่อสร้าง Table โครงสร้างเสร็จสิ้น **แต่ไม่ได้รันคำสั่ง `bun run prisma/seed.cjs`** +* **ผลกระทบ:** ตาราง `User` ในฐานข้อมูลใหม่ทั้งหมดมีข้อมูล **0 คน** เมื่อผู้ใช้พยายามล็อกอินเข้าหลังบ้าน (`admin..kittisak.com`) ระบบ Backend จึงหาชื่อผู้ใช้ไม่พบ และส่ง Error `401 Unauthorized` ทันที นอกจากนี้ข้อมูลตั้งต้น เช่น เมนู, หมวดหมู่ และสินค้าตัวอย่างก็ไม่มีในระบบ +* **สาเหตุที่พลาด:** สรุปจบงานเร็วเกินไปหลังจากเช็ค HTTP 200 ของหน้าเว็บและหน้า API พื้นฐาน โดยไม่ได้ทำการทดสอบ Smoke Test ในส่วนของการ **Login ด้วยบัญชี Admin จริง** + +### ข้อผิดพลาดหลักที่ 2: วิเคราะห์ปัญหาออกนอกลู่นอกทาง (Over-complicating Troubleshooting) +* **สิ่งที่เกิดขึ้น:** เมื่อเกิดปัญหา Login ไม่ได้ แทนที่จะกลับมาเปิดอ่าน `DEPLOYMENT_GUIDE.md` ที่ระบุขั้นตอนการ Seed และ User Admin ไว้อย่างชัดเจน กลับไปไล่แกะ Hash Password ใน Database และตั้งข้อสงสัยเรื่อง `onParse` ในโค้ด Backend +* **สาเหตุที่พลาด:** ไม่ได้ยึดตาม Runbook ขั้นตอนการ Deploy มาตรฐานเป็น First Priority ในการตรวจสอบความสมบูรณ์ของระบบที่เพิ่งสร้างใหม่ + +--- + +## 2. Checklist การสร้าง Subdomain / Tenant ใหม่ (ห้ามข้ามขั้นตอนเด็ดขาด) + +ทุกครั้งที่มีการสร้าง Domain หรือ Subdomain ใหม่ ต้องปฏิบัติตามลำดับขั้นตอนดังนี้: + +### Step 1: DNS & Port Allocation +- [ ] กำหนดพอร์ตที่ไม่ซ้ำกับโปรเจกต์เดิม: + - Backend API Port (เช่น `3055`, `3056`, ...) + - Website SSR Port (เช่น `3006`, `3007`, ...) +- [ ] ผูก DNS Records หรือ Wildcard A Record ชี้มาที่ IP เซิร์ฟเวอร์ให้เรียบร้อย + +### Step 2: Database Provisioning +- [ ] สร้างฐานข้อมูลใหม่ใน PostgreSQL: + ```bash + docker exec -i arokro_postgres psql -U postgres -c "CREATE DATABASE _db;" + ``` +- [ ] Push Schema ตารางเข้าฐานข้อมูลใหม่: + ```bash + cd /home/ti/projects/-api/apps/backend + bunx prisma db push + ``` + +### Step 3: Database Seeding (จุดที่เคยลืม - บังคับทำทันที!) +- [ ] รันคำสั่ง Seed ข้อมูลเริ่มต้นและบัญชี Admin: + ```bash + cd /home/ti/projects/-api/apps/backend + bun run prisma/seed.cjs + ``` +- [ ] ตรวจสอบว่ามี Admin User ในตารางจริง: + ```bash + docker exec -i arokro_postgres psql -U postgres -d _db -c "SELECT id, username, role FROM \"User\";" + ``` + *(ต้องเห็น user `admin` / role `ADMIN` จำนวน 1 แถว)* + +### Step 4: Firewall & Network +- [ ] เปิดพอร์ต Backend และ SSR ใน UFW: + ```bash + sudo ufw allow /tcp + sudo ufw allow /tcp + ``` +- [ ] ตรวจสอบว่ากฎ `ufw-user-input` ไม่บล็อกพอร์ตภายในเครื่อง + +### Step 5: Nginx & SSL Certbot +- [ ] สร้าง Nginx Config สำหรับ 4 ส่วน: + - `main` (SSR Website & Reverse Proxy ไปที่ SSR Port) + - `api` (Reverse Proxy ไปที่ Backend Port) + - `spa` (Static Web Root `/usr/share/nginx/html//spa`) + - `admin` (Static Web Root `/usr/share/nginx/html//admin`) +- [ ] ขอใบรับรอง SSL (Let's Encrypt Certbot) ให้ครบทุก Subdomain +- [ ] Reload Nginx: `docker exec -it nginx nginx -s reload` + +### Step 6: Automated Post-Receive Hook & Git Remote +- [ ] สร้าง Bare Git Repo: `/home/ti/git/.git` +- [ ] ตั้งค่า Hook `hooks/post-receive` พร้อมสิทธิ์ `chmod +x` +- [ ] เพิ่ม Git Remote ที่เครื่อง Local: + ```bash + git remote add demo- ti@kittisak.com:/home/ti/git/.git + ``` + +--- + +## 3. Smoke Test Verification (ต้องผ่านครบทุกข้อก่อนส่งมอบงาน) + +ห้ามประกาศว่าเสร็จงานจนกว่าจะรันคำสั่งทดสอบครบทั้ง 5 ข้อนี้: + +1. **ทดสอบ Website SSR:** + ```bash + curl -I https://.kittisak.com/th + # ต้องได้ HTTP 200 OK + ``` + +2. **ทดสอบ Backend API Status:** + ```bash + curl -I https://api..kittisak.com/api/categories + # ต้องได้ HTTP 200 OK + ``` + +3. **ทดสอบ Static SPA & Admin:** + ```bash + curl -I https://spa..kittisak.com + curl -I https://admin..kittisak.com + # ต้องได้ HTTP 200 OK + ``` + +4. **ทดสอบ Admin Login API (CRITICAL):** + ```bash + curl -X POST https://api..kittisak.com/api/auth/login \ + -H "Content-Type: application/json" \ + -d '{"username":"admin","password":"homaroma123"}' + # ผลลัพธ์ต้องเป็น: {"success":true,"token":"...","user":{"username":"admin"}} + ``` + +5. **ตรวจสอบตาราง User ในฐานข้อมูล:** + - ตาราง `User` ต้องมีอย่างน้อย 1 คน + - ข้อมูลสินค้าในตาราง `Product` ต้องมากกว่า 0