210 lines
9.1 KiB
Markdown
210 lines
9.1 KiB
Markdown
# คู่มือการติดตั้งโปรเจกต์ใหม่ (New Project Deployment Guide)
|
|
|
|
เอกสารนี้รวบรวมขั้นตอนการสร้างสภาพแวดล้อม (Environment) และการตั้งค่าระบบสำหรับลูกค้ารายใหม่ (เช่น โปรเจกต์ `pkh`) โดยอ้างอิงจากโครงสร้างระบบปัจจุบันบนเซิร์ฟเวอร์ `kitizone.com`
|
|
|
|
> [!NOTE]
|
|
> ระบบปัจจุบันใช้ **Bare Git Repository** ในการรับโค้ดและรัน Deployment Hook (post-receive)
|
|
> โปรเจกต์มี 4 โดเมนย่อย: เว็บไซต์หลัก (Next.js), SPA (React), Admin Panel (React), และ API (Elysia.js)
|
|
|
|
---
|
|
|
|
## 1. เตรียม Git Repository (Bare Repo)
|
|
|
|
บน Server ให้สร้างโฟลเดอร์สำหรับรับโค้ด:
|
|
|
|
```bash
|
|
# กำหนดชื่อโปรเจกต์
|
|
PROJECT_NAME="pkh"
|
|
|
|
# สร้าง Bare Repo
|
|
mkdir -p /home/ti/git/${PROJECT_NAME}.git
|
|
cd /home/ti/git/${PROJECT_NAME}.git
|
|
git init --bare
|
|
```
|
|
|
|
---
|
|
|
|
## 2. ขอ SSL Certificate & ตั้งค่า Nginx
|
|
|
|
เนื่องจากใช้ Nginx ผ่าน Docker เราจะต้องรัน Certbot แบบ Standalone เพื่อขอ Certificate
|
|
|
|
### 2.1 ปิด Nginx ชั่วคราว
|
|
```bash
|
|
cd /home/ti/projects/MyNginxMain
|
|
docker compose stop nginx
|
|
```
|
|
|
|
### 2.2 ขอ SSL ด้วย Certbot
|
|
เปลี่ยนชื่อโดเมนให้ตรงกับลูกค้า:
|
|
```bash
|
|
docker compose run --rm certbot certonly --standalone \
|
|
-d ${PROJECT_NAME}.kitizone.com \
|
|
-d spa.${PROJECT_NAME}.kitizone.com \
|
|
-d admin.${PROJECT_NAME}.kitizone.com \
|
|
-d api.${PROJECT_NAME}.kitizone.com
|
|
```
|
|
|
|
### 2.3 สร้าง Nginx Config Files
|
|
เข้าไปที่ `/home/ti/projects/MyNginxMain/nginx/conf.d/` และสร้างไฟล์ `.conf` สำหรับ 4 โดเมน โดยใช้ `admin.pkh.kitizone.com.conf` เป็นต้นแบบ:
|
|
|
|
> [!IMPORTANT]
|
|
> - สำหรับเว็บไซต์ (Next.js) และ API: ใช้ `proxy_pass http://192.168.1.167:<PORT>;`
|
|
> - สำหรับ SPA และ Admin: ตั้งค่า `root /usr/share/nginx/html/${PROJECT_NAME}/spa;` ไว้ที่ **ระดับ server block** (ห้ามใส่ใน location / เพื่อไม่ให้ติดปัญหา CORS หรือ 404 สำหรับไฟล์ static)
|
|
|
|
**ตัวอย่างโครงสร้าง Nginx สำหรับ Admin/SPA:**
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name admin.pkh.kitizone.com;
|
|
ssl_certificate /etc/letsencrypt/live/admin.pkh.kitizone.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/admin.pkh.kitizone.com/privkey.pem;
|
|
|
|
root /usr/share/nginx/html/pkh/admin;
|
|
|
|
location / {
|
|
index index.html index.htm;
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
expires max;
|
|
log_not_found off;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2.4 สตาร์ท Nginx
|
|
```bash
|
|
docker compose up -d nginx
|
|
```
|
|
|
|
---
|
|
|
|
## 3. สร้าง Database
|
|
|
|
เข้าไปใน Container ของ Postgres เพื่อสร้างฐานข้อมูลใหม่:
|
|
|
|
```bash
|
|
docker exec -it arokro_postgres bash
|
|
psql -U postgres -c "CREATE DATABASE ${PROJECT_NAME}db;"
|
|
exit
|
|
```
|
|
|
|
---
|
|
|
|
## 4. เปิด Firewall (UFW) ให้พอร์ตใหม่
|
|
|
|
กำหนดพอร์ตใหม่สำหรับ Next.js (เช่น `3003`) และ Backend API (เช่น `3052`)
|
|
> [!WARNING]
|
|
> หากลืมเปิด Firewall ขั้นตอนนี้ Nginx จะตอบกลับด้วย 504 Gateway Timeout ทันที!
|
|
|
|
```bash
|
|
sudo ufw allow 3003/tcp
|
|
sudo ufw allow 3052/tcp
|
|
sudo ufw reload
|
|
```
|
|
|
|
---
|
|
|
|
## 5. กำหนดค่า Environment (.env)
|
|
|
|
สร้างโฟลเดอร์สำหรับเก็บโค้ด (ซึ่งจะถูกโคลนมาจาก Git):
|
|
```bash
|
|
mkdir -p /home/ti/projects/${PROJECT_NAME}-api
|
|
mkdir -p /home/ti/projects/${PROJECT_NAME}-website
|
|
```
|
|
|
|
สร้างไฟล์ `.env` สำหรับ API ที่ `/home/ti/projects/${PROJECT_NAME}-api/apps/backend/.env`:
|
|
```ini
|
|
PORT=3052
|
|
DATABASE_URL="postgresql://postgres:password@localhost:5132/pkhdb?schema=public"
|
|
NODE_ENV=production
|
|
APP_URL="https://api.pkh.kitizone.com"
|
|
BACKEND_PUBLIC_URL="https://api.pkh.kitizone.com"
|
|
CORS_ORIGIN="https://admin.pkh.kitizone.com,https://spa.pkh.kitizone.com,https://pkh.kitizone.com"
|
|
```
|
|
> [!TIP]
|
|
> **สำคัญมาก:** Backend ของระบบ (Bun) จะอ่านไฟล์ `.env` ในโฟลเดอร์ `apps/backend/` เป็นหลัก ดังนั้นต้องระบุ `CORS_ORIGIN` ให้ครบถ้วนเพื่อไม่ให้หน้าบ้าน (React) ติดปัญหา CORS (Error 404/Failed to load resource)
|
|
|
|
---
|
|
|
|
## 6. ตั้งค่า Git Hook (post-receive)
|
|
|
|
นำสคริปต์ `post-receive` ไปวางที่ `/home/ti/git/${PROJECT_NAME}.git/hooks/post-receive`
|
|
|
|
**จุดที่ต้องแก้ไขใน Script:**
|
|
1. แก้ตัวแปรด้านบนสุด:
|
|
```bash
|
|
TARGET_BACKEND="/home/ti/projects/pkh-api"
|
|
TARGET_WEBSITE="/home/ti/projects/pkh-website"
|
|
TARGET_SPA="/home/ti/projects/MyNginxMain/nginx/html/pkh/spa"
|
|
TARGET_ADMIN="/home/ti/projects/MyNginxMain/nginx/html/pkh/admin"
|
|
|
|
PM2_NAME_BACKEND="pkh-backend"
|
|
PM2_NAME_WEBSITE="pkh-website"
|
|
```
|
|
2. แก้ไข Port ชั่วคราว (ถ้ามีการ copy ecosystem.config.js จาก homaroma):
|
|
```bash
|
|
sed -i 's/homaroma/pkh/g' $TARGET_BACKEND/ecosystem.config.js
|
|
sed -i 's/PORT: 3002/PORT: 3003/g' $TARGET_WEBSITE/ecosystem.config.js
|
|
```
|
|
3. **(สำคัญมาก)** เพิ่มคำสั่ง `sleep 10` หลังการสตาร์ท Backend:
|
|
```bash
|
|
echo ">>> Managing PM2 Process: $PM2_NAME_BACKEND..."
|
|
$PM2 startOrReload $TARGET_BACKEND/ecosystem.config.js --only $PM2_NAME_BACKEND --env production --update-env
|
|
echo "✅ PM2 process '$PM2_NAME_BACKEND' is running. Waiting 10s for it to fully start..."
|
|
sleep 10
|
|
```
|
|
*(ป้องกันปัญหาที่ Next.js Build เริ่มทำงานทันทีและ fetch API พังเพราะ Backend เพิ่งถูก restart ไปหมาดๆ)*
|
|
|
|
ตั้งสิทธิ์การรัน:
|
|
```bash
|
|
chmod +x /home/ti/git/${PROJECT_NAME}.git/hooks/post-receive
|
|
```
|
|
|
|
---
|
|
|
|
## 7. Deploy โค้ด (จากเครื่องนักพัฒนา)
|
|
|
|
ที่เครื่องของคุณ (Developer):
|
|
```bash
|
|
# แอดเซิร์ฟเวอร์ใหม่
|
|
git remote add pkh ti@kitizone.com:/home/ti/git/pkh.git
|
|
|
|
# สั่ง Deploy
|
|
git push pkh master
|
|
```
|
|
|
|
รอจนกว่าสคริปต์ post-receive จะจัดการ Build ทั้ง Backend, Website (SSR), Admin, และ SPA จนเสร็จ
|
|
|
|
---
|
|
|
|
## 8. Seed ฐานข้อมูล (ทำครั้งแรกครั้งเดียว)
|
|
|
|
หลังจาก Push สำเร็จแล้ว Database จะมีตารางต่างๆ สร้างขึ้นมา แต่ยังไม่มีข้อมูลพื้นฐาน ให้รัน Seed Script:
|
|
|
|
```bash
|
|
ssh ti@kitizone.com
|
|
|
|
# รันคำสั่ง Seed
|
|
cd /home/ti/projects/${PROJECT_NAME}-api/apps/backend
|
|
export PATH=$PATH:/home/ti/.bun/bin:/home/ti/.nvm/versions/node/v22.17.1/bin
|
|
bun run prisma/seed.cjs
|
|
```
|
|
|
|
ระบบจะสร้าง:
|
|
- เมนูพื้นฐาน (Core Menus)
|
|
- ข้อมูลพื้นฐาน (แบรนด์, หมวดหมู่ - ไม่ seed สินค้า)
|
|
- บัญชี Admin (`admin` / `homaroma123`)
|
|
|
|
---
|
|
|
|
## สรุปปัญหาที่มักพบ (Troubleshooting)
|
|
|
|
1. **Next.js Build พัง (504 Gateway Timeout ตอนดึง Sitemap):**
|
|
- สาเหตุ: API หรือ Database ดาวน์, หรือลืมเปิดพอร์ต Backend ด้วยคำสั่ง `ufw allow`
|
|
- แก้ไข: ตรวจสอบพอร์ต UFW ว่าเปิดแล้ว และเช็คสคริปต์ว่ามี `sleep 10` ให้ API บูทเสร็จหรือไม่
|
|
2. **Admin/SPA พัง (CORS Policy หรือ 404 Assets):**
|
|
- สาเหตุ: ลืมระบุ `CORS_ORIGIN` หรือตั้งค่า `root` ของ Nginx ไว้ผิดที่ (ผิด Block)
|
|
- แก้ไข: เติม CORS ใน `apps/backend/.env` แล้ว Restart PM2, และนำ `root` ออกมาไว้ระดับ `server { ... }` ใน Nginx
|