Runbook production
VPS Linux mới
Domain mới: vinhmkt.net

Chuyển nhà Diễm My AI sang VPS mới

Mục tiêu: clone lõi trung tâm của hệ thống hiện tại sang VPS Linux mới, public bằng domain mới để tránh xung đột với production cũ. Tài liệu này ưu tiên copy-paste chạy được, có cảnh báo điều kiện cần, và có checklist verify rõ ràng.

OpenClaw
bot.vinhmkt.net → 127.0.0.1:18789
9router
9router.vinhmkt.net → 127.0.0.1:20128
YouTube Analyzer V12
yt.vinhmkt.net → 127.0.0.1:3002
Điền nhanh để lệnh tự thay IP

Nhập IP thật vào đây, các block lệnh bên dưới sẽ tự thay placeholder để anh copy cho đỡ sửa tay.

1) Kiến trúc đích

ServiceDomain mớiPort localGhi chú
OpenClaw Gateway / Control UIbot.vinhmkt.net127.0.0.1:18789Không mở public trực tiếp port 18789
9router9router.vinhmkt.net127.0.0.1:20128Dashboard + API qua nginx
YouTube Analyzer V12yt.vinhmkt.net127.0.0.1:3002Chạy bằng systemd service

1b) Chi tiết các ứng dụng

OpenClaw Gateway

Nền tảng AI agent chính — xử lý chat, Telegram bot, cron job, memory, và điều phối các dịch vụ khác.

  • Port: 127.0.0.1:18789
  • Service: systemctl --user status openclaw-gateway
  • Config: /root/.openclaw/openclaw.json
  • Workspace: /opt/diemmy/workspace
  • Control UI: https://bot.vinhmkt.net

9router

AI model routing layer — chuyển request tới nhiều provider (Google, OpenAI, Claude, Ollama local) với combo fallback tự động.

  • Port: 127.0.0.1:20128
  • Service: systemctl status 9router
  • Source: /opt/9router
  • State/DB: /var/lib/9router/db.jsonquan trọng, chứa combo + API key + provider config
  • Dashboard: https://9router.vinhmkt.net
  • API: https://9router.vinhmkt.net/v1
  • Active combos: main-fallback, vision-main, text-main, local-main

YouTube Analyzer V12 🎬

Web app phân tích kênh YouTube bằng AI — đánh giá nội dung, xu hướng, so sánh kênh, và tạo blueprint kênh mới.

  • Port: 127.0.0.1:3002
  • Service: systemctl status youtube-analyzer-v12
  • Source: /opt/youtube-analyzer-v12
  • DB: /opt/youtube-analyzer-v12/data/users.db (SQLite — users, reports, blueprints, quota, shares)
  • GitHub: github.com/vinhvgs/youtube-analyzer
  • Admin: vinhnv.mkt@gmail.com (is_admin=1)
  • Version: v12.1 (tag: v12.1-bugfix-quota-share-blueprint)

Tính năng chính:

  • 🔍 Phân tích kênh: thống kê video, views, trending, AI insights, viral score
  • 📊 So sánh kênh: đặt cạnh nhau nhiều kênh, content gap analysis
  • 🎯 Blueprint: tạo bản thiết kế kênh mới 4 bước (Identity → Calendar → Production → Brand Kit)
  • 💾 Lưu/chia sẻ: báo cáo lưu DB, share link có thời hạn, xuất Excel/PDF
  • 📈 Quota tracking: theo dõi YouTube API quota theo ngày (SQLite-backed, sống sót qua restart)
  • 🔐 Auth: Google OAuth + email/password, tier-based limits, admin panel
  • 🤖 AI: dùng 9router API (đơn giản cấu hình trong .env: AI_BASE_URL + AI_API_KEY)

File quan trọng khi migrate:

  • /opt/youtube-analyzer-v12/ — toàn bộ source + dist
  • /opt/youtube-analyzer-v12/data/users.dbdatabase chính, không được mất
  • /opt/youtube-analyzer-v12/.env — API keys, JWT secret, Google OAuth
  • /etc/systemd/system/youtube-analyzer-v12.service — systemd unit

Lưu ý sau khi migrate:

  • Nếu đổi domain 9router, cần sửa AI_BASE_URL trong .env
  • GOOGLE_CALLBACK_URL trong .env cũng cần đổi sang domain mới
  • Admin user đã có sẵn trong DB, không cần promote lại
  • Node.js v22+ required, npm install rồi npm run build nếu cần rebuild

2) Điều kiện cần trước khi chạy

  1. VPS mới là Linux có systemd (Ubuntu/Debian là đẹp nhất).
  2. Đã có quyền root SSH vào VPS mới.
  3. Đã quản lý được DNS của vinhmkt.net.
  4. Đã trỏ DNS của bot.vinhmkt.net, 9router.vinhmkt.net, yt.vinhmkt.net về IP VPS mới.
  5. VPS mới mở inbound tối thiểu 80/tcp443/tcp.
  6. VPS mới SSH được sang VPS cũ bằng root hoặc user đủ quyền đọc các thư mục nguồn.
  7. VPS cũ vẫn đang là source of truth và chưa bị sửa linh tinh thêm.
Mở firewall tối thiểu (nếu VPS dùng UFW)
command -v ufw >/dev/null 2>&1 && ufw allow 80/tcp
command -v ufw >/dev/null 2>&1 && ufw allow 443/tcp
command -v ufw >/dev/null 2>&1 && ufw status || true

Nếu VPS mới đang dùng UFW, chạy block trên để đảm bảo web + SSL truy cập được từ ngoài vào. Nếu máy không cài UFW thì block này sẽ tự bỏ qua. Không cần mở public các port nội bộ như 18789, 20128, 3002.

Nếu thiếu một trong các điều kiện trên, nhiều lệnh bên dưới sẽ chạy lỗi hoặc restore ra trạng thái nửa vời.

3) Biến cần thay trước khi copy-paste

Thay các giá trị này trước khi chạy lệnh:

Biến môi trường cần thay
OLD_VPS_IP=<OLD_VPS_IP>
NEW_VPS_IP=<IP_VPS_MOI>
NEW_DOMAIN_BOT=bot.vinhmkt.net
NEW_DOMAIN_ROUTER=9router.vinhmkt.net
NEW_DOMAIN_YT=yt.vinhmkt.net

4) Bước 1 — Chuẩn bị DNS

Tạo 3 bản ghi A:

Bản ghi DNS
bot.vinhmkt.net      A      <IP_VPS_MOI>
9router.vinhmkt.net  A      <IP_VPS_MOI>
yt.vinhmkt.net       A      <IP_VPS_MOI>

Kiểm tra DNS đã ăn chưa:

Check DNS
dig +short bot.vinhmkt.net
dig +short 9router.vinhmkt.net
dig +short yt.vinhmkt.net

Phải ra đúng IP của VPS mới.

5) Bước 2 — Chuẩn bị base VPS mới

Cài package nền
apt-get update
apt-get install -y curl git rsync nginx certbot python3-certbot-nginx ca-certificates
Cài Node.js 22
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs
node -v
npm -v
Cài đúng OpenClaw version đang chạy trên máy cũ
npm install -g openclaw@2026.4.1
openclaw --version

Khuyến nghị mạnh: VPS mới nên cài đúng OpenClaw 2026.4.1 trước để clone lõi giống hệt hệ đang chạy. Không nên nhảy version mới ngay trong bước migrate ban đầu.

Tạo thư mục đích
mkdir -p /opt/diemmy/workspace
mkdir -p /opt/9router
mkdir -p /opt/youtube-analyzer-v12
mkdir -p /root/.openclaw
mkdir -p /root/.config/systemd/user/openclaw-gateway.service.d

6) Bước 3 — Copy lõi từ VPS cũ

Các lệnh này chạy trên VPS mới.

Test SSH sang VPS cũ trước khi rsync
ssh root@<OLD_VPS_IP> 'echo SSH_OK'

Nếu chưa ra SSH_OK thì đừng chạy rsync vội, kẻo đứng giữa đường rồi ngơ người luôn anh ạ.

Copy workspace + state + services
rsync -aHAX --info=progress2 root@<OLD_VPS_IP>:/opt/diemmy/workspace/ /opt/diemmy/workspace/
rsync -aHAX --info=progress2 root@<OLD_VPS_IP>:/root/.openclaw/ /root/.openclaw/
rsync -aHAX --info=progress2 root@<OLD_VPS_IP>:/var/lib/9router/ /var/lib/9router/
rsync -aHAX --info=progress2 root@<OLD_VPS_IP>:/opt/9router/ /opt/9router/
rsync -aHAX --info=progress2 root@<OLD_VPS_IP>:/opt/youtube-analyzer-v12/ /opt/youtube-analyzer-v12/
rsync -aHAX root@<OLD_VPS_IP>:/etc/systemd/system/9router.service /etc/systemd/system/9router.service
rsync -aHAX root@<OLD_VPS_IP>:/etc/systemd/system/youtube-analyzer-v12.service /etc/systemd/system/youtube-analyzer-v12.service
rsync -aHAX root@<OLD_VPS_IP>:/root/.config/systemd/user/ /root/.config/systemd/user/
Kiểm tra file đã về đủ chưa
ls -la /opt/diemmy/workspace | head
ls -la /root/.openclaw | head
ls -la /opt/9router | head
ls -la /opt/youtube-analyzer-v12 | head
ls -la /etc/systemd/system/9router.service
ls -la /etc/systemd/system/youtube-analyzer-v12.service
ls -la /root/.config/systemd/user/openclaw-gateway.service

7) Bước 4 — Chỉnh cấu hình domain mới

Backup trước khi sửa
cp /root/.openclaw/openclaw.json /root/.openclaw/openclaw.json.before-vinhmkt-migration
cp /opt/9router/.env /opt/9router/.env.before-vinhmkt-migration 2>/dev/null || true
Tìm domain cũ
grep -Rni "nvv.io.vn" /root/.openclaw/openclaw.json /opt/diemmy/workspace 2>/dev/null | head -100
Đổi sang domain mới (openclaw.json + allowedOrigins)
perl -0pi -e 's#https://bot\.nvv\.io\.vn#https://bot.vinhmkt.net#g' /root/.openclaw/openclaw.json
perl -0pi -e 's#https://9router\.nvv\.io\.vn#https://9router.vinhmkt.net#g' /root/.openclaw/openclaw.json
perl -0pi -e 's#https://yt\.nvv\.io\.vn#https://yt.vinhmkt.net#g' /root/.openclaw/openclaw.json
Nhớ kiểm tra thêm: trong openclaw.json có key gateway.controlUi.allowedOrigins — phải đổi hết domain cũ sang domain mới ở đây nữa, nếu không Control UI sẽ bị CORS chặn khi truy cập qua bot.vinhmkt.net.
Kiểm tra lại
grep -n "vinhmkt.net" /root/.openclaw/openclaw.json || true
Rà domain cũ toàn hệ để khỏi sót
grep -Rni "nvv.io.vn" /root/.openclaw /opt/9router /opt/diemmy/workspace /opt/youtube-analyzer-v12 2>/dev/null | head -200
Lưu ý: nếu có script/docs/URL hardcode khác trong workspace, xử lý từng case sau. Đừng cố dọn sạch mọi docs ngay từ đầu nếu mục tiêu là bring-up lõi trước.

8) Bước 5 — Khởi động service lõi

OpenClaw gateway
loginctl enable-linger root
systemctl --user daemon-reload
systemctl --user enable openclaw-gateway
systemctl --user restart openclaw-gateway
systemctl --user status openclaw-gateway --no-pager
curl -s http://127.0.0.1:18789/health
openclaw status --deep
9router
systemctl daemon-reload
systemctl enable 9router
systemctl restart 9router
systemctl status 9router --no-pager
ss -ltnp | grep ':20128\b' || true
curl -I http://127.0.0.1:20128
YouTube Analyzer V12
systemctl daemon-reload
systemctl enable youtube-analyzer-v12
systemctl restart youtube-analyzer-v12
systemctl status youtube-analyzer-v12 --no-pager
ss -ltnp | grep ':3002\b' || true
curl -fsS http://127.0.0.1:3002/api/health

9) Bước 6 — Dựng nginx reverse proxy

bot.vinhmkt.net
cat > /etc/nginx/sites-available/bot.vinhmkt.net <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name bot.vinhmkt.net;

    location / {
        proxy_pass http://127.0.0.1:18789;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
9router.vinhmkt.net
cat > /etc/nginx/sites-available/9router.vinhmkt.net <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name 9router.vinhmkt.net;

    location / {
        proxy_pass http://127.0.0.1:20128;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
yt.vinhmkt.net
cat > /etc/nginx/sites-available/yt.vinhmkt.net <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name yt.vinhmkt.net;

    location / {
        proxy_pass http://127.0.0.1:3002;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
EOF
Enable sites + reload nginx
ln -sf /etc/nginx/sites-available/bot.vinhmkt.net /etc/nginx/sites-enabled/bot.vinhmkt.net
ln -sf /etc/nginx/sites-available/9router.vinhmkt.net /etc/nginx/sites-enabled/9router.vinhmkt.net
ln -sf /etc/nginx/sites-available/yt.vinhmkt.net /etc/nginx/sites-enabled/yt.vinhmkt.net
/usr/sbin/nginx -t
systemctl reload nginx

10) Bước 7 — Xin SSL

Điều kiện cần:
  • DNS đã trỏ đúng về VPS mới
  • nginx đang trả được HTTP port 80
  • port 80 và 443 không bị firewall chặn
Xin SSL
certbot --nginx -d bot.vinhmkt.net -d 9router.vinhmkt.net -d yt.vinhmkt.net
Check renew timer
systemctl status certbot.timer --no-pager || true

11) Bước 8 — Verify đầy đủ

Verify local ports
ss -ltnp | grep -E ':(18789|20128|3002)\b' || true
Verify OpenClaw
openclaw status --deep
openclaw cron list
openclaw memory status --deep
Verify 9router
systemctl status 9router --no-pager
curl -I -L https://9router.vinhmkt.net
Verify YouTube Analyzer
systemctl status youtube-analyzer-v12 --no-pager
curl -fsS http://127.0.0.1:3002/api/health
curl -I -L https://yt.vinhmkt.net
curl -I -L https://yt.vinhmkt.net/api/health
Verify Bot UI
curl -I -L https://bot.vinhmkt.net
Verify service auto-start sau reboot
systemctl is-enabled 9router
systemctl is-enabled youtube-analyzer-v12
systemctl --user is-enabled openclaw-gateway
Pass condition:
  • Không có failed unit (systemctl --failed)
  • OpenClaw status lên bình thường, channels connected
  • 9router có service + endpoint + dashboard truy cập được
  • YouTube Analyzer có 200/api/health OK
  • Domain mới đều truy cập được qua HTTPS
  • Cả 3 service đều enabled (auto-start sau reboot)

12) Lỗi thường gặp

Case 1 — systemctl --user không chạy ổn

Nguyên nhân thường là chưa bật linger cho root hoặc user manager chưa lên đúng.

Fix + diagnose linger
loginctl enable-linger root
loginctl show-user root
systemctl --user daemon-reload
systemctl --user status openclaw-gateway --no-pager
journalctl --user -u openclaw-gateway -n 100 --no-pager

Case 2 — 9router lên service nhưng route/combo lỗi

Thường do thiếu env/db/auth state từ VPS cũ.

Check nhanh 9router
systemctl status 9router --no-pager
ss -ltnp | grep ':20128\b' || true
curl -I http://127.0.0.1:20128

Case 3 — YouTube Analyzer lên service nhưng API lỗi

Thường do thiếu .env hoặc DB auth/data chưa copy đủ.

Check nhanh V12
systemctl status youtube-analyzer-v12 --no-pager
curl -fsS http://127.0.0.1:3002/api/health
ls -la /opt/youtube-analyzer-v12
ls -la /opt/youtube-analyzer-v12/data

Case 4 — nginx -t báo command not found

Dùng full path:

nginx full path
/usr/sbin/nginx -t
systemctl reload nginx

13) Rollback nếu có vấn đề

Điểm mạnh của kế hoạch này: VPS cũ và domain cũ vẫn sống riêng, nên rollback rất nhẹ.

Rollback logic
# Không cần đụng VPS cũ.
# Nếu VPS mới có lỗi:
# 1) dừng service lỗi trên VPS mới
# 2) chỉnh tiếp nội bộ
# 3) test lại bằng domain mới
# production cũ vẫn an toàn

14) Bản siêu ngắn để copy-paste

Runbook ngắn
apt-get update
apt-get install -y curl git rsync nginx certbot python3-certbot-nginx ca-certificates
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
apt-get install -y nodejs
npm install -g openclaw@2026.4.1

mkdir -p /opt/diemmy/workspace /opt/9router /opt/youtube-analyzer-v12 /root/.openclaw /root/.config/systemd/user/openclaw-gateway.service.d /var/lib/9router

ssh root@<OLD_VPS_IP> 'echo SSH_OK'
rsync -aHAX root@<OLD_VPS_IP>:/opt/diemmy/workspace/ /opt/diemmy/workspace/
rsync -aHAX root@<OLD_VPS_IP>:/root/.openclaw/ /root/.openclaw/
rsync -aHAX root@<OLD_VPS_IP>:/opt/9router/ /opt/9router/
rsync -aHAX root@<OLD_VPS_IP>:/var/lib/9router/ /var/lib/9router/
rsync -aHAX root@<OLD_VPS_IP>:/opt/youtube-analyzer-v12/ /opt/youtube-analyzer-v12/
rsync -aHAX root@<OLD_VPS_IP>:/etc/systemd/system/9router.service /etc/systemd/system/9router.service
rsync -aHAX root@<OLD_VPS_IP>:/etc/systemd/system/youtube-analyzer-v12.service /etc/systemd/system/youtube-analyzer-v12.service
rsync -aHAX root@<OLD_VPS_IP>:/root/.config/systemd/user/ /root/.config/systemd/user/

loginctl enable-linger root
systemctl --user daemon-reload
systemctl --user enable openclaw-gateway
systemctl --user restart openclaw-gateway

systemctl daemon-reload
systemctl enable 9router
systemctl restart 9router
systemctl enable youtube-analyzer-v12
systemctl restart youtube-analyzer-v12