Scripts moi (PowerShell admin trên VPS Windows Server):
- setup-sql-db.ps1: tao DB SolutionErp + grant db_owner cho vrapp (user shared voi VIETREPORT). Idempotent.
- setup-iis-sites.ps1: app pool SolutionErp-Api (NoManagedCode + AlwaysRunning + no idle) + 3 site (SolutionErp-Api/Admin/User) voi host header, C:\inetpub\solution-erp\{api,fe-admin,fe-user,logs,uploads}. Placeholder index.html + SPA web.config voi URL rewrite fallback + security headers. Firewall rule. ACL grant AppPool identity Modify. Naming prefix SolutionErp-* tranh conflict VIETREPORT.
- setup-ssl.ps1: download win-acme v2.2.9 → issue cert Let's Encrypt 3 domain (api/admin/user.huypham.vn) qua HTTP-01 challenge + auto install IIS binding + HTTP→HTTPS redirect + scheduled task 90d renew.
- setup-gitea-runner.ps1: download act_runner.exe → register voi Gitea git.baocaogiaoduc.vn, install Windows service, labels windows-latest,self-hosted,windows,x64 (cho phep share voi VIETREPORT).
FE production config:
- fe-admin/.env.production + fe-user/.env.production: VITE_API_BASE_URL=https://api.huypham.vn
- fe-admin/src/lib/api.ts + fe-user/src/lib/api.ts: BASE_URL = (import.meta.env.VITE_API_BASE_URL ?? '') + '/api'
- Dev: empty prefix → /api qua Vite proxy :5443
- Prod: https://api.huypham.vn/api (cross-origin CORS da config AllowedOrigins)
Docs:
- docs/guides/vps-setup.md MOI (master runbook): prereq, 4 script chay theo thu tu, set 5 Gitea secrets, first deploy, appsettings.Production.json pattern (file hoac user-secrets), smoke test 3 curl, post go-live checklist (doi admin password, rotate secrets chat-exposed, backup schedule, disable Swagger prod, monitor logs), table co-existence VIETREPORT
- CLAUDE.md root: add vps-setup.md reference
Gitea repo da setup (extern):
- https://git.baocaogiaoduc.vn/vietreport-admin/solution-erp (private)
- Secrets set via API: IIS_HOST=103.124.94.38, IIS_USER=Administrator, DB_CONNECTION (voi vrapp password), JWT_SECRET placeholder
- CON THIEU: IIS_PASSWORD (Windows admin — user cung cap), JWT_SECRET real value (64-char tu vps-jwt-key.txt — user update qua Gitea UI)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.1 KiB
6.1 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.huypham.vn,admin.huypham.vn,user.huypham.vn,git.baocaogiaoduc.vn→103.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:
- .NET 10 Hosting Bundle cài chưa? Check:
dotnet --list-runtimes | grep 'Microsoft.AspNetCore.App 10' - Nếu chưa → tải từ https://dotnet.microsoft.com/en-us/download/dotnet/10.0 → "Hosting Bundle"
- Sau cài →
iisreset
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.huypham.vn/health/live # → Healthy
curl https://api.huypham.vn/health/ready # → Healthy (DB probe)
# Login
curl -X POST https://api.huypham.vn/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@solutionerp.local","password":"Admin@123456"}'
# → accessToken JWT
# FE
open https://admin.huypham.vn # fe-admin login page
open https://user.huypham.vn # fe-user login page
# SSL grade
# https://www.ssllabs.com/ssltest/analyze.html?d=api.huypham.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 URLhttps://api.huypham.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
deployment-iis.md— IIS setup chi tiếtcicd.md— Gitea Actionssecurity-checklist.md— pre go-liverunbook.md— operationsscripts/setup-*.ps1— automation scripts