Files
solution-erp/docs/guides/vps-setup.md
pqhuy1987 66c1a5c170
All checks were successful
Deploy SOLUTION_ERP / build-deploy (push) Successful in 2m52s
[CLAUDE] Rebrand: 3 domain huypham.vn → solutions.com.vn + migrate script
User request: anh trỏ 3 subdomain mới về VPS IP 103.124.94.38:
  - api.huypham.vn        → api.solutions.com.vn
  - admin.huypham.vn      → admin.solutions.com.vn
  - user.huypham.vn       → eoffice.solutions.com.vn

Verified DNS: cả 3 resolve 103.124.94.38 ✓

Update 17 file repo:
FE (4): fe-admin/.env.production + fe-user/.env.production
        (VITE_API_BASE_URL → https://api.solutions.com.vn)
        fe-admin/src/lib/{api,realtime}.ts + fe-user equivalents (comment)
BE (1): appsettings.Production.json.example — CORS AllowedOrigins
CI/CD (1): .gitea/workflows/deploy.yml — smoke test URL
Scripts (3): setup-iis-sites (DomainApi/Admin/User), setup-ssl (3 host),
             deploy-all (verify curls)
Docs (5): STATUS, HANDOFF, PROJECT-MAP, vps-setup, gotchas
Skill (1): iis-deploy-runbook — 3 site table + description
Email admin@huypham.vn giữ nguyên (Let's Encrypt contact — không phải
domain serve).

Thêm scripts/migrate-domains.ps1 — 1-shot VPS migration:
  1. Pre-flight: resolve DNS 3 domain → verify IP VPS khớp
  2. Add HTTP binding mới cho 3 IIS site (giữ binding cũ làm fallback)
  3. Run win-acme xin 3 cert Let's Encrypt qua HTTP-01 challenge
     (auto add HTTPS binding + http→https redirect)
  4. Verify /health/live + /health/ready + 2 FE endpoint
  5. (Optional -RemoveOld) xóa binding huypham.vn sau verify OK
Rollback: nếu fail, binding cũ vẫn active → site serve qua huypham.vn.

Anh chạy trên VPS:
  cd C:\solution-erp\scripts  ;  .\migrate-domains.ps1
  # Sau 1-2 ngày verify stable:
  .\migrate-domains.ps1 -RemoveOld -SkipCert
2026-04-24 09:43:05 +07:00

6.2 KiB

VPS Setup — Master Runbook

Step-by-step deploy SOLUTION_ERP lên VPS Windows Server shared với VIETREPORT. VPS: 103.124.94.38 (cùng chỗ với Gitea, SQL, IIS).

0. Context

  • VPS OS: Windows Server (có IIS + SQL Server)
  • Shared với: VIETREPORT project — naming isolation bắt buộc
  • DNS đã trỏ: api.solutions.com.vn, admin.solutions.com.vn, eoffice.solutions.com.vn, git.baocaogiaoduc.vn103.124.94.38
  • Prefix resources: SolutionErp-* (app pool, site), SolutionErp (DB), C:\inetpub\solution-erp\ (path)

1. Prerequisites trên VPS (đã có sẵn với VIETREPORT)

  • Windows Server 2019/2022
  • IIS + URL Rewrite + Application Initialization (VIETREPORT đã dùng)
  • SQL Server với login sa + vrapp (shared app user)
  • Gitea tại git.baocaogiaoduc.vn
  • Port 80/443 firewall open

Cần verify trên VPS:

2. Run setup scripts trên VPS

Copy folder scripts/ từ repo lên VPS (vd C:\solution-erp\scripts\):

# 1. SQL DB + grant vrapp
cd C:\solution-erp\scripts
.\setup-sql-db.ps1 -SaPassword '<SA_PASSWORD_FROM_SECRETS_VAULT>'

# 2. IIS sites + app pool
.\setup-iis-sites.ps1
# → Tạo SolutionErp-Api pool + 3 site (SolutionErp-Api/Admin/User)
# → C:\inetpub\solution-erp\{api,fe-admin,fe-user,logs,uploads}

# 3. HTTPS cert (win-acme, Let's Encrypt)
.\setup-ssl.ps1
# → Issue cert cho 3 domain + auto-renew scheduled task

# 4. Gitea runner (registration token lấy từ Gitea admin settings)
.\setup-gitea-runner.ps1 -RegistrationToken '<token>'

3. Set Gitea Actions secrets

Vào https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/settings/actions/secrets — 5 secret:

Name Value Ghi chú
IIS_HOST 103.124.94.38 đã set
IIS_USER Administrator đã set (hoặc username Windows khác)
IIS_PASSWORD (Windows admin password) ⚠️ user set tay — token/secret chat không commit
JWT_SECRET (64 chars từ vps-jwt-key.txt) ⚠️ cần update — placeholder hiện tại
DB_CONNECTION Server=localhost;Database=SolutionErp;User Id=vrapp;Password=... đã set với vrapp password

4. First deploy

# Trên máy dev — push main trigger workflow
git push origin main

# Trên Gitea:
# https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp/actions
# → 1 run đang chạy (build BE + 2 FE + deploy)

5. Set appsettings.Production.json trên VPS

cd C:\inetpub\solution-erp\api
# Copy từ template
cp appsettings.Production.json.example appsettings.Production.json

# Edit thay placeholder:
# - ConnectionStrings.Default → Password=<vrapp password>
# - Jwt.Secret → <64 chars từ vps-jwt-key.txt>

Hoặc dùng user-secrets (safer — không file trên disk):

cd C:\inetpub\solution-erp\api
dotnet user-secrets set "Jwt:Secret" "<64-char-from-file>"
dotnet user-secrets set "ConnectionStrings:Default" "Server=localhost;Database=SolutionErp;User Id=vrapp;Password=...;..."

6. Smoke test sau deploy

# Health check
curl https://api.solutions.com.vn/health/live     # → Healthy
curl https://api.solutions.com.vn/health/ready    # → Healthy (DB probe)

# Login
curl -X POST https://api.solutions.com.vn/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@solutionerp.local","password":"Admin@123456"}'
# → accessToken JWT

# FE
open https://admin.solutions.com.vn    # fe-admin login page
open https://eoffice.solutions.com.vn     # fe-user login page

# SSL grade
# https://www.ssllabs.com/ssltest/analyze.html?d=api.solutions.com.vn

7. Sau go-live (bắt buộc)

  • Đổi password admin từ Admin@123456 → mạnh. Warning log xuất hiện khi còn dùng default.
  • Rotate secrets đã post trong chat (SA, vrapp, Gitea token, JWT) — tất cả đã vượt khỏi VPS, cần đổi mới
  • Backup SQL daily schedule: schtasks /Create /TN 'SolutionErp SQL Backup' /TR 'powershell -File C:\solution-erp\scripts\backup-sql.ps1 -SaPassword <pw>' /SC DAILY /ST 02:00 /RU SYSTEM
  • Disable Swagger prod: Program.cs đã có if (IsDevelopment()) — verify URL https://api.solutions.com.vn/swagger → 404
  • Monitor: kiểm C:\inetpub\solution-erp\logs\ ngày đầu, watch for ERR

8. Co-existence với VIETREPORT — checklist

Resource SOLUTION_ERP VIETREPORT Conflict?
App pool name SolutionErp-Api VietReport-* (assumed)
Site name SolutionErp-Api/Admin/User VietReport-*
Path C:\inetpub\solution-erp\ C:\inetpub\vietreport\ (assumed)
SQL DB SolutionErp VietReport (assumed)
SQL user vrapp (shared db_owner) vrapp Shared — OK (cùng login, khác DB)
Port 80/443 Host header routing Host header routing IIS cho phép share qua Host header
Firewall rule HTTP In (SolutionErp) HTTP In (VietReport)
Gitea runner vps-win-* labels windows-latest shared Runner serve multi repo qua labels

9. Troubleshooting

Xem runbook.md cho operations hàng ngày + deployment-iis.md cho troubleshoot chi tiết.

Common issues khi co-exist:

  • Port 80 conflict — check netstat -ano | findstr :80 → kill service ngoài IIS
  • IIS default site block new site — disable "Default Web Site" hoặc đổi binding
  • win-acme fail HTTP-01 — port 80 phải reachable từ Internet (không local firewall block)
  • SQL user vrapp không có quyền DB SolutionErp — script setup-sql-db.ps1 đã handle, re-run nếu skip

10. Liên quan