Files
lcbp3/docs/deployment-setup-guide.md
admin 2e50bcaa58
CI / CD Pipeline / build (push) Successful in 5m27s
CI / CD Pipeline / deploy (push) Successful in 5m18s
690522:0839 227 #02
2026-05-22 08:39:26 +07:00

11 KiB

// File: docs/deployment-setup-guide.md // Change Log // - 2026-05-22: แก้ไข IP Address ของเซิร์ฟเวอร์ AI จาก 192.168.10.100 เป็น 192.168.10.8 เพื่อให้ตรงกับสภาพแวดล้อมจริง

คู่มือการตั้งค่าและการ Deploy ระบบ (Deployment Setup Guide)

Project: NAP-DMS (LCBP3)
Version: 1.9.5
Last Updated: 2026-05-21
Stack: NestJS + Next.js + MariaDB + Redis + Elasticsearch + Qdrant
Target Platform: QNAP TS-473A (Container Station) + ASUSTOR AS5403T (Gitea Runner)


🏗️ 1. สถาปัตยกรรมระบบการ Deploy (Deployment Architecture)

ระบบ DMS แยกการทำงานออกเป็นเซิร์ฟเวอร์หลัก 2 เครื่องเพื่อความปลอดภัยและประสิทธิภาพสูงสุด (Server Role Separation):

  • QNAP Server (TS-473A) - 192.168.10.8 (VLAN 10): เป็นเซิร์ฟเวอร์หลักที่รันฐานข้อมูล, Cache, Search Engine และรัน Application Containers (Frontend + Backend) รวมถึง Git Server (Gitea) และ Nginx Proxy Manager (NPM)
  • ASUSTOR Server (AS5403T) - 192.168.10.9 (VLAN 10): เป็นเซิร์ฟเวอร์สำหรับรัน CI/CD Gitea Runner (act_runner) เพื่อแยกโหลดการ Build โค้ดออกจากโปรดักชันเซิร์ฟเวอร์
[ ASUSTOR Runner ] (192.168.10.9)
       │
       │ SSH (Via Private Key)
       ▼
[ QNAP TS-473A ] (192.168.10.8)
       ├── Git Pull & Build (BuildKit)
       └── Restart Stack (docker compose --force-recreate)

🔐 2. การตั้งค่า SSH Key Authentication (Persistent SSH Setup)

เนื่องจาก QNAP จะรีเซ็ต Directory / ไปเป็น RAM หลังการ Reboot ทำให้เกิดปัญหา SSH Key หาย เราจำเป็นต้องตั้งค่าให้เป็น Persistent SSH:

2.1 บน ASUSTOR (Gitea Runner)

สร้าง SSH Key Pair และเก็บไว้ในโฟลเดอร์ถาวร:

  • Private Key: /etc/config/ssh/gitea-runner
  • Public Key: /etc/config/ssh/gitea-runner.pub

2.2 บน QNAP (Target Server)

  1. นำเนื้อหา Public Key ไปเพิ่มในไฟล์ authorized_keys:

    mkdir -p /etc/config/ssh
    # เพิ่ม public key ลงไป (ต้องอยู่ภายในบรรทัดเดียว ห้ามเว้นวรรคผิดพลาด)
    nano /etc/config/ssh/authorized_keys
    
  2. แก้ไขไฟล์คอนฟิก SSH ของ QNAP (สำคัญมาก: ต้องแก้ไฟล์ที่ /etc/config/ssh/sshd_config เท่านั้น ไม่ใช่ /etc/ssh/sshd_config):

    # ตั้งค่า AuthorizedKeysFile ชี้ไปที่ absolute path ของโฟลเดอร์คอนฟิกถาวร
    AuthorizedKeysFile /etc/config/ssh/authorized_keys
    

    หมายเหตุ: ห้ามใช้ relative path เช่น .ssh/authorized_keys เด็ดขาด เพราะระบบจะไปหาที่ /share/homes/admin/.ssh/ แทนที่จะเป็น /root/.ssh/

  3. Reload QNAP SSH daemon (เนื่องจาก QNAP ไม่มี pgrep และ systemctl ให้ใช้คำสั่งนี้):

    kill -HUP $(ps | grep "/usr/sbin/sshd -f /etc/config" | grep -v grep | awk '{print $1}')
    

📁 3. การเตรียมโครงสร้างโฟลเดอร์บน QNAP

ล็อกอินเข้า QNAP ผ่าน SSH และรันคำสั่งเตรียม Directory โครงสร้างพื้นฐาน:

# 1. โฟลเดอร์หลักสำหรับ App Source และ Build Script
mkdir -p /share/np-dms/app/source

# Clone repository (ครั้งแรกครั้งเดียว)
cd /share/np-dms/app/source
git clone https://git.np-dms.work/np-dms/lcbp3.git

# 2. โฟลเดอร์สำหรับเก็บไฟล์อัปโหลดและ Logs
mkdir -p /share/np-dms/data/uploads/temp
mkdir -p /share/np-dms/data/uploads/permanent
mkdir -p /share/np-dms/data/logs/backend

# 3. ตั้งค่าสิทธิ์โฟลเดอร์ (UID 1001 คือ NestJS User ภายใน Container)
chown -R 1001:1001 /share/np-dms/data/uploads
chown -R 1001:1001 /share/np-dms/data/logs/backend
chmod -R 750 /share/np-dms/data/uploads

# 4. โฟลเดอร์สำหรับ persistent volumes ของ DB/Services อื่นๆ
mkdir -p /volume1/lcbp3/volumes/mariadb-data
mkdir -p /volume1/lcbp3/volumes/redis-data
mkdir -p /volume1/lcbp3/volumes/elastic-data

📝 4. การจัดการ Environment Variables (.env)

สร้างไฟล์ .env ที่ /share/np-dms/app/.env บน QNAP โดยตรง
⚠️ กฎความปลอดภัย (Tier 1): ห้าม Commit ไฟล์นี้ขึ้น Git หรือเก็บในโฟลเดอร์ Source Code เด็ดขาด!

# File: /share/np-dms/app/.env

# Application Configuration
NODE_ENV=production
APP_NAME=LCBP3-DMS
NEXT_PUBLIC_API_URL=https://backend.np-dms.work/api
AUTH_URL=https://lcbp3.np-dms.work

# Database (MariaDB native UUID v7 - ADR-019)
DB_HOST=mariadb
DB_PORT=3306
DB_USERNAME=lcbp3_user
DB_PASSWORD=<STRONG_DATABASE_PASSWORD>
DB_DATABASE=lcbp3_dms
DB_POOL_SIZE=20

# Redis Cache & BullMQ (ADR-008)
REDIS_HOST=cache
REDIS_PORT=6379
REDIS_PASSWORD=<STRONG_REDIS_PASSWORD>
REDIS_DB=0

# Security Credentials (Tier 1)
JWT_SECRET=<สร้างด้วย openssl rand -base64 32>
AUTH_SECRET=<สร้างด้วย openssl rand -base64 32>

# File Upload Security (Tier 1)
UPLOAD_PATH=/app/uploads
MAX_FILE_SIZE=52428800 # 50MB
ALLOWED_FILE_TYPES=.pdf,.doc,.docx,.xls,.xlsx,.dwg,.zip

# ClamAV Antivirus
CLAMAV_HOST=lcbp3-clamav
CLAMAV_PORT=3310

# AI Services Boundary (ADR-023/ADR-023A - Isolation on Admin Desktop)
OLLAMA_URL=http://192.168.10.8:11434
AI_HOST_URL=http://192.168.10.8:11434
AI_QDRANT_URL=http://192.168.10.8:6333

🔄 5. การตั้งค่า CI/CD Gitea Actions

ใน Gitea Web UI ไปที่ repository → SettingsActionsSecrets เพื่อเพิ่มตัวแปรลับ (Secrets) ที่ใช้เชื่อมต่อ SSH ไปยัง QNAP:

Secret Name Value คำอธิบาย
HOST 192.168.10.8 IP Address ของ QNAP (VLAN 10)
PORT 22 พอร์ต SSH (Default: 22)
USERNAME admin สิทธิ์แอดมินในการควบคุม Container ของ QNAP
SSH_KEY -----BEGIN OPENSSH PRIVATE KEY-----... เนื้อหาในไฟล์คีย์ส่วนตัวจาก ASUSTOR (/etc/config/ssh/gitea-runner)

🚀 6. ขั้นตอนการ Deploy

6.1 การ Deploy อัตโนมัติ (Automated CI/CD)

เมื่อมีการ Push โค้ดไปยังกิ่ง main ระบบ Gitea Actions จะรับงานไปรันบน ASUSTOR Runner:

  1. เชื่อมต่อ SSH ไปยัง QNAP (สิทธิ์ admin ผ่าน SSH Key)
  2. สั่ง git pull ดึงโค้ดล่าสุดลงโฟลเดอร์ /share/np-dms/app/source/lcbp3
  3. เรียกใช้สคริปต์ @/scripts/deploy.sh ของโครงการเพื่อทำการ build และ deploy

6.2 การ Deploy ด้วยตนเอง (Manual Deploy)

หากพบปัญหาเรื่องเน็ตเวิร์ก หรือต้องการรัน Deploy เองตรงจาก QNAP:

# 1. SSH เข้า QNAP
ssh admin@192.168.10.8

# 2. ไปที่โฟลเดอร์ Repository และ pull โค้ดล่าสุด
cd /share/np-dms/app/source/lcbp3
git pull origin main

# 3. รันสคริปต์ Deploy
bash scripts/deploy.sh

รายละเอียดการทำงานของ deploy.sh:

  • Build Step (BuildKit): รันคำสั่ง Build Image ในแบบขนานกัน (Parallel) เพื่อลดเวลาก่อสร้าง:
    docker build -f backend/Dockerfile -t lcbp3-backend:latest . &
    docker build -f frontend/Dockerfile -t lcbp3-frontend:latest . &
    
  • Recreate Container: ใช้ --force-recreate ควบคู่กับ Environment file โปรดักชัน:
    docker compose --env-file /share/np-dms/app/.env -f specs/04-Infrastructure-OPS/04-00-docker-compose/QNAP/app/docker-compose-app.yml up -d --force-recreate
    
  • Health Check: ตรวจสอบความถูกต้องของการสตาร์ตระบบ (Timeout 60 วินาที) ก่อนรายงานผลความสำเร็จ

🆘 7. การกู้คืนระบบและการแก้ปัญหา (Rollback & Troubleshooting)

7.1 การ Rollback ระบบ

หากหลังจาก Deploy พบว่าระบบทำงานบกพร่อง (Critical Bug):

  1. ผ่าน Gitea UI: ไปที่แท็บ Actions → เลือกกิ่งที่มีเสถียรภาพตัวล่าสุด (Stable Commit) → กดปุ่ม Re-run Jobs
  2. รันคำสั่งตรงบน QNAP (SSH):
    cd /share/np-dms/app/source/lcbp3
    # ตรวจหาแฮชคอมมิตก่อนหน้าที่มีความเสถียร
    git log --oneline -10
    # ย้อนกลับโค้ด
    git checkout <stable-commit-hash>
    # รันสร้างและดีพลอยใหม่ด้วยโค้ดเดิม
    bash scripts/deploy.sh
    

7.2 ปัญหาตู้คอนเทนเนอร์ค้าง (Container Removal Timeout)

หากตอน Deploy มีอาการค้างที่กระบวนการลบตู้อันเดิม:

# Force stop และลบตู้อันที่ค้าง
docker kill backend frontend 2>/dev/null || true
docker rm -f backend frontend 2>/dev/null || true

# ทำความสะอาด Cache และ Prune ของตกค้าง
docker system prune -f --volumes

# รีสตาร์ตตู้ Stack ทั้งหมดใหม่อีกครั้ง
bash scripts/deploy.sh

// Change Log: // - 2026-05-21: จัดทำเอกสารคู่มือขั้นตอนการเซ็ตอัปการ Deploy สำหรับทีมปฏิบัติการและผู้พัฒนา (v1.9.5)