คู่มือการติดตั้งระบบ (Deployment Guide)
อ้างอิง TOR: ข้อ 4.11.2 (Deployment Guide), ข้อ 4.4.7 (ติดตั้งบน Cloud ของมหาวิทยาลัย), ข้อ 4.6.2 (แยกสภาพแวดล้อม Dev/Production), ภาคผนวก ก ข้อ 1.5.2 (โดเมน dhammaverse.mbu.ac.th) ฉบับ: 1.0 — วันที่ 3 ตุลาคม พ.ศ. 2569
สถานะ: ระบบสาธิตติดตั้งและทดสอบบนเครื่องเดียว (sandbox) ตามหัวข้อ 2–4 แล้ว ส่วน การติดตั้งบน Kubernetes ของมหาวิทยาลัย (หัวข้อ 5–8) ยังไม่ได้ดำเนินการจริง เพราะ sandbox ไม่มี cluster, registry, DNS และ credential ของมหาวิทยาลัย — ข้อ 4.4.7 และ ก.1.5.2 จึงมีสถานะ todo และ 4.6.2 เป็น partial ในหน้า
/torขั้นตอนในหัวข้อ 5–8 อ้างอิงไฟล์ส่งมอบจริง (infra/helm/mbu-buddhist-ai/,.github/workflows/ci-cd.yml) แต่ยังไม่ผ่านการรันบนคลัสเตอร์จริง เอกสารนี้ไม่ระบุรหัสผ่านหรือ API key ใด ๆ
1. ภาพรวมการติดตั้ง
| รูปแบบ | ใช้เมื่อ | องค์ประกอบ | สถานะ |
|---|---|---|---|
| ระบบสาธิต (sandbox / เครื่องเดียว) | สาธิต พัฒนา ทดสอบ ตรวจรับเบื้องต้น | Next.js แอปเดียว + SQLite + ไฟล์ในเครื่อง (+ HTTPS self-signed) | ติดตั้งและใช้งานแล้ว |
| Production บน Kubernetes | ให้บริการจริง | Helm chart 8 microservices + PostgreSQL 16 + Redis 7 + Elasticsearch + TEI + Object Storage + Ingress/cert-manager + HPA + WAF | ไฟล์ส่งมอบพร้อม ยังไม่ได้ติดตั้ง |
2. ความต้องการของเครื่อง (ระบบสาธิต)
- Node.js ≥22 และ npm
sqlite3(ใช้โดยสคริปต์สำรอง/กู้คืน),openssl(สร้างใบรับรอง/คีย์)- Python 3 (เฉพาะเมื่อต้องการดึงคลังความรู้ใหม่ด้วย
npm run data:fetch) - ไม่ต้องใช้ Docker หรือ database server
- เบราว์เซอร์ Chromium/Chrome สำหรับ E2E (ตั้ง
CHROMIUM_PATHถ้าไม่อยู่ที่/usr/bin/chromium)
3. ติดตั้งระบบสาธิต (Local / Sandbox)
# 1) ติดตั้ง dependencies
npm install
# 2) ตั้งค่าสภาพแวดล้อม
cp .env.example .env
# แก้ .env: AUTH_SECRET (≥32 ตัวอักษร), DATA_ENCRYPTION_KEY="base64:$(openssl rand -base64 32)"
# TYPHOON_API_KEY = คีย์ที่มหาวิทยาลัยจัดหา (ไม่ใส่ = ใช้ Mock LLM อัตโนมัติ)
# 3) สร้างฐานข้อมูล prisma/dev.db (+ trigger ห้ามแก้/ลบ AuditLog)
npx prisma migrate dev
# 4) ข้อมูลตั้งต้น: ผู้ใช้สาธิต, config, prompt, guardrail, คลังความรู้, ชุดทดสอบ, ข้อมูลใช้งานย้อนหลัง 14 วัน
npx prisma db seed
# 5) รัน
npm run dev # http://localhost:3000
npm run dev -- -p 3210 # เปลี่ยนพอร์ต (ระบบสาธิตใช้ 3210)
ตรวจว่าระบบขึ้น:
curl -s http://localhost:3000/api/health # { ok: true, ..., index: { chunks: … } }
curl -sI http://localhost:3000/th | head -1 # HTTP/1.1 200
curl -s http://localhost:3000/api/openapi.json | head -c 200
3.1 HTTPS แบบ self-signed (สาธิต ก.2.1.2)
bash scripts/generate-dev-cert.sh # สร้าง certs/dev-key.pem + certs/dev-cert.pem (RSA 2048, อายุ 365 วัน, CN=localhost)
npm run start:https # = node server.https.js → https://localhost:3443
curl -sk https://localhost:3443/th | head -c 100
ตัวแปรเสริม: HTTPS_PORT (ค่าเริ่มต้น 3443), HTTPS_HOST, HTTPS_KEY_FILE, HTTPS_CERT_FILE, NODE_ENV=production (ใช้ผล npm run build) — เบราว์เซอร์จะเตือนใบรับรองไม่น่าเชื่อถือเพราะเป็น self-signed ซึ่งคาดหมายได้ในระบบสาธิต
3.2 Production build บนเครื่องเดียว (แยก Dev/Prod — TOR 4.6.2)
npm run db:prod:setup # DATABASE_URL=file:./prod.db → prisma migrate deploy + seed (สร้าง prisma/prod.db)
npm run build
npm start # next start (Next.js โหลด .env.production: prod.db + ENABLE_HSTS)
| ไฟล์ | สภาพแวดล้อม | ฐานข้อมูล |
|---|---|---|
.env.development | npm run dev | prisma/dev.db |
.env.production | npm run build / npm start | prisma/prod.db (+ เปิด HSTS) |
| ฐานข้อมูลทดสอบ | vitest | prisma/test-template-<pid>.db (สร้าง/ลบอัตโนมัติ) |
prisma/perf.db | ทดสอบบัญชีจำนวนมาก | สร้างโดย npm run seed:perf-users |
3.3 บัญชีสาธิตตามบทบาท
บัญชีสาธิตสร้างจาก seed/users.json (รหัสผ่านอยู่ในไฟล์นั้นและใน README — ไม่ระบุในเอกสารนี้; ต้องเปลี่ยนก่อนใช้งานจริง)
| อีเมล | บทบาท | หมายเหตุ |
|---|---|---|
| superadmin@mbu.ac.th | SUPER_ADMIN | ทุกสิทธิ์ รวมสำรอง/ทำลายข้อมูล เปลี่ยน role |
| admin@mbu.ac.th | ADMIN | ผู้ดูแลระบบ |
| committee@mbu.ac.th | ADMIN | บัญชีสำหรับคณะกรรมการตรวจรับ (TOR 7.2.8) |
| monk.demo@example.com | GENERAL_USER | เปิดสิทธิ์ Dhamma Talk แล้ว |
| student.demo@example.com | GENERAL_USER | ค่าเริ่มต้น (Dhamma Talk ปิด) |
| suspended.demo@example.com | GENERAL_USER | สถานะระงับ (ทดสอบการปฏิเสธการเข้าสู่ระบบ) |
นอกจากนี้ seed สร้าง “ผู้ใช้สาธิต 01–30” (demo.userNN@example.com) และข้อมูลการใช้งานสังเคราะห์สำหรับ Dashboard — ส่วนผู้ดูแล (/admin) เข้าได้เฉพาะ IP ใน ADMIN_IP_ALLOWLIST
3.4 ทดสอบหลังติดตั้ง
npm test # unit + API + openapi-coverage
npm run test:e2e # Playwright 3 viewport (dev server ที่ E2E_PORT, ค่าเริ่มต้น 3210)
npm run report:all # รายงาน security, perf, restore-test, ingestion, evaluation, sla
3.5 งานตามรอบบนเครื่องเดียว
| งาน | วิธี |
|---|---|
| ลบบทสนทนาหมดอายุ | อัตโนมัติใน process (ทุก retention.purgeIntervalMinutes) หรือ npm run purge:conversations |
| สำรองข้อมูล | ตั้ง cron เรียก bash scripts/backup-db.sh (ดู /documents/backup-restore-guide) |
| Log | logs/app.log (หมุนไฟล์ด้วย logrotate ของระบบปฏิบัติการ) |
4. การเปลี่ยนค่าที่ต้องทำก่อนเปิดใช้งานจริง (Checklist)
- ตั้ง
AUTH_SECRETและDATA_ENCRYPTION_KEYใหม่ที่สุ่มอย่างปลอดภัย (เก็บสำรองDATA_ENCRYPTION_KEYไว้อย่างปลอดภัย — หากหายจะถอดรหัสอีเมล/ชื่อผู้ใช้ไม่ได้) - เปลี่ยนรหัสผ่านบัญชีผู้ดูแลทั้งหมด และระงับ/ลบบัญชีสาธิตที่ไม่ใช้
- ตั้ง
ADMIN_IP_ALLOWLISTเป็นเครือข่ายของมหาวิทยาลัย และวางระบบหลัง reverse proxy ที่เขียนx-forwarded-forทับ - ใส่ API key ของ LLM ที่มหาวิทยาลัยจัดหา แล้วกด ทดสอบ LLM ที่
/admin/ai-config - ตั้ง
NEXT_PUBLIC_BASE_URLเป็นโดเมนจริง (https) เพื่อให้ cookie มีแฟล็กSecure, เปิดENABLE_HSTS=1 - ตั้ง OAuth (Google/Facebook) และ SMTP จริงถ้าต้องการ
- ลบข้อมูลการใช้งานสังเคราะห์ก่อนใช้งานจริง (
/admin/data-destructionขอบเขตบทสนทนา/โทเคน/ผู้ใช้ทั่วไป) หรือ seed ฐานข้อมูลใหม่โดยไม่รันขั้นข้อมูลสังเคราะห์
5. Production บน Kubernetes ด้วย Helm (แผนติดตั้ง)
5.1 สถาปัตยกรรมเป้าหมาย
flowchart TB
DNS["dhammaverse.mbu.ac.th (DNS → Load Balancer)"] --> WAF["WAF / Anti-DDoS ของผู้ให้บริการคลาวด์"]
WAF --> ING["Ingress (NGINX) + TLS (cert-manager)"]
ING -->|"/"| WEB["frontend: mbu-buddhist-ai-web (Next.js SSR, release แยก)"]
ING -->|"/api/auth, /api/me, /api/privacy, /api/admin/users ..."| ID["identity"]
ING -->|"/api/chat, /api/conversations, /api/messages"| CHAT["chat"]
ING -->|"/api/chunks"| RET["retrieval"]
ING -->|"/api/admin/knowledge-base"| INGS["ingestion"]
ING -->|"/api/admin/evaluation"| EVAL["evaluation"]
ING -->|"/api/status, /api/admin/ai-config, prompts, guardrails ..."| CFG["config"]
ING -->|"/api/documents, /api/admin/dashboard, alerts, sla-report, defect-log"| REP["report"]
CHAT --> AIO["ai-orchestrator (LangGraph, ภายใน cluster)"]
AIO --> RET
AIO --> LLM["Typhoon API (OpenAI-compatible)"]
subgraph DATA["namespace mbu-data / mbu-ai"]
PG[("PostgreSQL 16")]
RD[("Redis 7")]
ES[("Elasticsearch")]
TEI["TEI: bge-m3 / bge-reranker-v2-m3"]
S3[["Object Storage (S3)"]]
end
ID & CHAT & CFG & REP & EVAL --> PG
RET --> ES
RET --> TEI
INGS --> S3
CFG --> RD
5.2 ไฟล์ส่งมอบ (infra/helm/mbu-buddhist-ai/)
| ไฟล์ | เนื้อหา |
|---|---|
Chart.yaml | chart mbu-buddhist-ai version 0.1.0, kubeVersion >=1.27.0-0 |
values.yaml | ค่าร่วม: 8 services (image, port 3001–3008, replicas, resources, HPA CPU 70%, ingressPaths), env ร่วม (PostgreSQL/Redis/Elasticsearch/TEI/Typhoon/S3), existingSecret, pod/container security context, probes /api/health, Ingress + TLS + ตัวอย่าง WAF annotation |
values-dev.yaml / values-test.yaml / values-prod.yaml | ค่าทับรายสภาพแวดล้อม |
templates/deployment-<service>.yaml ×8 | Deployment ต่อ service |
templates/service.yaml, hpa.yaml, ingress.yaml, configmap.yaml, _helpers.tpl | Service (ClusterIP), HPA (autoscaling/v2), Ingress, ConfigMap (env ร่วม + APP_ENV + <SERVICE>_SERVICE_URL ของทุก service) |
5.3 สามสภาพแวดล้อม (TOR 4.6.2)
| Environment | Namespace | values | Host | Trigger (CI/CD) | ลักษณะ |
|---|---|---|---|---|---|
| dev | mbu-dev | values-dev.yaml | dev.dhammaverse.mbu.ac.th | push → branch develop | replica เดียวทุก service, ปิด HPA, LOG_LEVEL=debug, cert Let’s Encrypt staging, ฐานข้อมูล mbu_buddhist_ai_dev |
| test | mbu-test | values-test.yaml | test.dhammaverse.mbu.ac.th | push → branch release/* | SIT/UAT, เปิด HPA ขนาดเล็ก (max 2–3), ฐานข้อมูล mbu_buddhist_ai_test |
| prod | mbu-prod | values-prod.yaml | dhammaverse.mbu.ac.th | git tag v* บน main + อนุมัติ environment prod | HA ≥2 replicas (chat/ai-orchestrator 3), HPA (chat/ai-orchestrator max 12), soft pod anti-affinity ข้าม node, WAF |
5.4 สิ่งที่ต้องเตรียมก่อนติดตั้ง
- Kubernetes ≥1.27 พร้อม metrics-server (จำเป็นต่อ HPA), NGINX Ingress Controller (หรือปรับ
ingress.className/annotation ตาม controller ที่มี), cert-manager พร้อม ClusterIssuerletsencrypt-prod/letsencrypt-staging - บริการข้อมูล: PostgreSQL 16, Redis 7, Elasticsearch, TEI (bge-m3, bge-reranker-v2-m3), Object Storage — ตาม hostname ใน
values*.yaml(postgresql.mbu-data.svc.cluster.localฯลฯ) หรือแก้ให้ตรงกับของจริง - Container registry (ค่าเริ่มต้น
ghcr.io, imagembu-ac-th/mbu-<service>-service) และimagePullSecretsถ้าเป็น private - Secret ชื่อ
mbu-buddhist-ai-secretsในแต่ละ namespace (สร้างด้วย External Secrets / Sealed Secrets / kubectl — ไม่อยู่ใน Git) มีคีย์:DB_PASSWORD,REDIS_PASSWORD,ELASTICSEARCH_PASSWORD,AUTH_SECRET,DATA_ENCRYPTION_KEY,OPENAI_API_KEY(คีย์ Typhoon),GEMINI_API_KEY/ANTHROPIC_API_KEY(ถ้าใช้),GOOGLE_OAUTH_CLIENT_SECRET,FACEBOOK_OAUTH_CLIENT_SECRET,SMTP_PASS - DNS และ IP allowlist ของส่วนผู้ดูแล (แนะนำแยก Ingress ของ
/api/adminแล้วใช้whitelist-source-range)
5.5 งานพัฒนาที่ต้องทำก่อนติดตั้ง Production ได้จริง
จากการตรวจ repository ปัจจุบัน — ระบบสาธิตเป็น Next.js แอปเดียว จึงยังต้อง:
- แยกโค้ดตาม bounded context เป็น 8 service (โครงสร้าง
src/domain/src/application/src/serverแบ่งไว้แล้ว) และสร้างservices/<name>/Dockerfile(CI อ้างถึงแต่ ยังไม่มีไฟล์ใน repository) พร้อม release ของ frontendmbu-buddhist-ai-web - เปลี่ยน Prisma datasource จาก
sqliteเป็นpostgresqlและสร้าง migration ใหม่ (รวม trigger ห้าม UPDATE/DELETEAuditLogแบบ PostgreSQL) - ย้ายสถานะในหน่วยความจำไป Redis (rate limit, คิวงาน ingestion → BullMQ, การจองโทเคน) และย้ายไฟล์อัปโหลดไป Object Storage
- implement
ElasticsearchSearchAdapter(ปัจจุบันเป็นโครง) และตั้งTEI_EMBED_URL/TEI_RERANK_URL - ทางเลือกระยะเปลี่ยนผ่าน: deploy แอปเดียว (Next.js) เป็น Deployment เดียวหลัง Ingress เดียวกันพร้อม PostgreSQL ก่อน แล้วค่อยแยก service
5.6 คำสั่งติดตั้ง/อัปเกรด
CHART=infra/helm/mbu-buddhist-ai
# ตรวจ chart ทั้ง 3 environment (เหมือนงาน lint ใน CI)
for e in dev test prod; do
helm lint "$CHART" -f "$CHART/values.yaml" -f "$CHART/values-$e.yaml"
helm template mbu-buddhist-ai "$CHART" -n "mbu-$e" -f "$CHART/values.yaml" -f "$CHART/values-$e.yaml" > /dev/null
done
# ติดตั้ง/อัปเกรด (ตัวอย่าง prod) — --atomic: ล้มเหลวแล้ว Helm ย้อนกลับเอง
helm upgrade --install mbu-buddhist-ai "$CHART" \
--namespace mbu-prod --create-namespace \
-f "$CHART/values.yaml" -f "$CHART/values-prod.yaml" \
--set global.image.tag=v1.0.0 \
--atomic --wait --timeout 15m --history-max 10
# ตรวจผล
kubectl -n mbu-prod get deploy,hpa,ingress -l app.kubernetes.io/instance=mbu-buddhist-ai
curl -fsS https://dhammaverse.mbu.ac.th/api/health
ปกติการ deploy ทำผ่าน pipeline อัตโนมัติ (/documents/cicd-pipeline) ซึ่งใช้คำสั่งเดียวกัน (dev/test timeout 10 นาที, prod 15 นาที)
5.7 Migration ฐานข้อมูลบน Production
ก่อนอัปเกรดเวอร์ชันที่มี migration: สำรองฐานข้อมูล (pg_dump / snapshot) → รัน npx prisma migrate deploy (Job หรือ init container ที่ชี้ DATABASE_URL ของ environment นั้น) → deploy แอป → smoke test
6. Rollback
| สถานการณ์ | วิธี |
|---|---|
helm upgrade ล้มเหลว (pod ไม่ ready ภายใน timeout) | --atomic ย้อนกลับ revision เดิมให้อัตโนมัติ |
| Deploy ผ่านแต่ smoke test ไม่ผ่าน (ใน CI) | step “Rollback (helm rollback) on failure” ย้อนไป revision ที่บันทึกไว้ก่อน deploy |
| พบปัญหาหลังใช้งาน | helm history mbu-buddhist-ai -n mbu-prod → helm rollback mbu-buddhist-ai <REVISION> -n mbu-prod --wait (เก็บประวัติ 10 revision --history-max 10, Deployment เก็บ revisionHistoryLimit: 5) |
| ปัญหาจากการตั้งค่า AI/Prompt (ไม่ใช่โค้ด) | ย้อนกลับในแอปทันที: /admin/ai-config → snapshot → ย้อนกลับ; /admin/prompts → ใช้เวอร์ชันก่อนหน้า (ไม่ต้อง redeploy) |
| Migration ฐานข้อมูลทำให้ข้อมูลเสีย | กู้คืนจาก backup ก่อน migration (/documents/backup-restore-guide) แล้ว rollback แอปเป็นเวอร์ชันที่ตรงกับ schema |
| ระบบสาธิตบนเครื่องเดียว | หยุดแอป → checkout เวอร์ชันก่อนหน้า → npm install && npm run build → bash scripts/restore-db.sh <ไฟล์สำรอง> ถ้า schema เปลี่ยน → เปิดแอป |
7. DNS และ TLS
| รายการ | Production (แผน) | ระบบสาธิต |
|---|---|---|
| โดเมน | dhammaverse.mbu.ac.th (prod), test. / dev.dhammaverse.mbu.ac.th | localhost |
| DNS | ระเบียน A/CNAME ชี้ Load Balancer ของ Ingress — มหาวิทยาลัยเป็นผู้จัดการโซน mbu.ac.th | ไม่มี — dhammaverse.mbu.ac.th ยัง resolve DNS ไม่ได้ ณ วันที่พัฒนา (ก.1.5.2 = todo) |
| TLS | cert-manager ออก/ต่ออายุใบรับรองอัตโนมัติ (cert-manager.io/cluster-issuer), secret dhammaverse-mbu-ac-th-tls, บังคับ redirect HTTPS (ssl-redirect, force-ssl-redirect) | self-signed server.https.js :3443 |
| HSTS | ENABLE_HSTS=1 | ตั้งใน .env.production (มีผลจริงเมื่อเสิร์ฟผ่าน HTTPS) |
| SSE/อัปโหลด | Ingress proxy-buffering: off, proxy-read/send-timeout: 300, proxy-body-size: 50m | — |
8. ความปลอดภัยของการติดตั้ง
- Pod:
runAsNonRoot(UID/GID 1000),seccompProfile: RuntimeDefault, containerreadOnlyRootFilesystem,allowPrivilegeEscalation: false, drop ALL capabilities - Secret อ้างผ่าน
$(KEY)ใน env ของ Deployment (ไม่อยู่ใน ConfigMap) - WAF/Anti-DDoS (ก.2.2.1): เลือกเปิดตัวอย่าง annotation ใน
values.yamlตามผู้ให้บริการคลาวด์ (ModSecurity + OWASP CRS, rate limit ที่ Ingress, AWS WAFv2/Shield, Azure Application Gateway WAF, Google Cloud Armor หรือ CDN/WAF ภายนอก) - คีย์ LLM: มหาวิทยาลัยเป็นผู้จัดหาและใส่เองใน Secret ของแต่ละ namespace (TOR 4.6.1)
9. สิ่งที่ทำไม่ได้ใน sandbox และเหตุผล
| รายการ | TOR | เหตุผล | สิ่งที่ส่งมอบแทน |
|---|---|---|---|
| ติดตั้งบน Cloud/Kubernetes ของมหาวิทยาลัย | 4.4.7 | ไม่มีคลัสเตอร์ บัญชีคลาวด์ หรือ kubeconfig ของมหาวิทยาลัย | Helm chart 3 environment + คู่มือนี้ + pipeline |
| โดเมน dhammaverse.mbu.ac.th | ก.1.5.2 | DNS ยังไม่ resolve และไม่มีสิทธิ์จัดการโซน | Ingress host ตั้งไว้แล้ว |
| Auto Scaling จริง | ก.1.6.2 | ต้องมีคลัสเตอร์ + metrics-server | templates/hpa.yaml |
| WAF / Anti-DDoS | ก.2.2.1 | เป็นบริการของผู้ให้บริการคลาวด์ | rate limit ระดับแอป + ตัวอย่าง annotation |
| Container image ของ 8 services | 4.6.3 | sandbox ไม่มี Docker และระบบสาธิตเป็นแอปเดียว | ขั้นตอนใน CI (ทำงานเมื่อมี Dockerfile และ DEPLOY_ENABLED=true) |
| PostgreSQL/Redis/Elasticsearch/TEI จริง | 2.6 | ไม่มี database/search server ใน sandbox | SQLite + ดัชนีในหน่วยความจำ + adapter interfaces |
| CI/CD บน GitHub Actions | 4.6.3 | ไม่ได้ push ไป GitHub ที่ตั้ง secrets | .github/workflows/ci-cd.yml |
| OAuth/SMTP จริง | ก.3.3.2, ก.4.10.2 | ไม่มี client secret / SMTP | Mock OAuth Provider, AlertEmailLog |