[CLAUDE] Scripts: rewrite 4 deploy PS1 ASCII-only for PS 5.1 compat
Some checks failed
Deploy SOLUTION_ERP / build-backend (push) Failing after 9s
Deploy SOLUTION_ERP / build-fe-admin (push) Has been cancelled
Deploy SOLUTION_ERP / build-fe-user (push) Has been cancelled
Deploy SOLUTION_ERP / deploy-iis (push) Has been cancelled

PowerShell 5.1 reads .ps1 files as locale codepage (not UTF-8 no BOM),
which corrupts multi-byte Vietnamese chars and breaks parsing. Rewrote
setup-iis-sites.ps1, setup-ssl.ps1, setup-gitea-runner.ps1, deploy-all.ps1
as ASCII-only. Also renamed $Host param to $HostName in Ensure-Site to
avoid collision with PowerShell built-in $Host automatic variable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
pqhuy1987
2026-04-21 14:17:36 +07:00
parent 85acf750b3
commit 169e268b28
4 changed files with 131 additions and 137 deletions

View File

@ -1,14 +1,14 @@
# Setup IIS sites + app pools cho SOLUTION_ERP trên VPS Windows Server
# Chia sẻ với VIETREPORT naming isolation: SolutionErp-* prefix để tránh conflict.
# Chạy trên VPS với admin privilege. Idempotent.
# Setup IIS sites + app pools for SOLUTION_ERP on VPS Windows Server.
# Shared with VIETREPORT - naming isolation: SolutionErp-* prefix to avoid conflict.
# Run on VPS with admin privilege. Idempotent.
#
# Usage:
# .\setup-iis-sites.ps1
#
# Prereq:
# - IIS cài + features: Application Initialization, URL Rewrite, ARR (optional)
# - .NET 10 Hosting Bundle cài
# - Port 80/443 firewall đã mở
# - IIS installed + features: Application Initialization, URL Rewrite, ARR (optional)
# - .NET 10 Hosting Bundle installed
# - Port 80/443 firewall open
$ErrorActionPreference = 'Stop'
Import-Module WebAdministration
@ -45,14 +45,18 @@ foreach ($p in @($Root, $PathApi, $PathAdmin, $PathUser, $PathLogs, $PathUploads
}
}
# Grant app pool identity write quyền
$acl = Get-Acl $Root
# Grant app pool identity write permission
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"IIS AppPool\$AppPoolApi", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")
$acl.SetAccessRule($rule)
try { Set-Acl -Path $Root -AclObject $acl } catch { Write-Warning " ACL set se fail neu app pool chua ton tai — bypass" }
try {
$acl = Get-Acl $Root
$acl.SetAccessRule($rule)
Set-Acl -Path $Root -AclObject $acl
} catch {
Write-Warning " ACL set may fail if app pool does not exist yet - will retry"
}
# ===================== 2. App pool (Api only, FE static) =====================
# ===================== 2. App pool (Api only, FE is static) =====================
Write-Step "App pool: $AppPoolApi"
if (-not (Test-Path "IIS:\AppPools\$AppPoolApi")) {
New-WebAppPool -Name $AppPoolApi | Out-Null
@ -65,12 +69,12 @@ Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name processModel.idleTimeout -Val
Set-ItemProperty "IIS:\AppPools\$AppPoolApi" -Name recycling.periodicRestart.time -Value "00:00:00"
Write-Host " Configured (NoManagedCode + AlwaysRunning + no idle timeout + no daily recycle)"
# Re-grant ACL sau khi pool tạo (identity cần tồn tại)
# Re-grant ACL after pool created (identity must exist)
try {
$acl = Get-Acl $Root
$acl.SetAccessRule($rule)
Set-Acl -Path $Root -AclObject $acl
Write-Host " ACL granted Modify cho IIS AppPool\$AppPoolApi"
Write-Host " ACL granted Modify to IIS AppPool\$AppPoolApi"
} catch {
Write-Warning " ACL fail: $_"
}
@ -78,15 +82,15 @@ try {
# ===================== 3. Sites =====================
function Ensure-Site {
param(
[string]$Name, [string]$Host, [string]$Path, [string]$AppPool
[string]$Name, [string]$HostName, [string]$PhysicalPath, [string]$AppPool
)
Write-Step "Site: $Name ($Host)"
Write-Step "Site: $Name ($HostName)"
if (-not (Test-Path "IIS:\Sites\$Name")) {
# Port 80 HTTP SSL sẽ thêm sau qua win-acme
# Port 80 HTTP - SSL added later via win-acme
$params = @{
Name = $Name
HostHeader = $Host
PhysicalPath = $Path
HostHeader = $HostName
PhysicalPath = $PhysicalPath
Port = 80
}
if ($AppPool) { $params.ApplicationPool = $AppPool }
@ -94,18 +98,18 @@ function Ensure-Site {
Write-Host " Created"
} else {
Write-Host " Exists"
Set-ItemProperty "IIS:\Sites\$Name" -Name physicalPath -Value $Path
Set-ItemProperty "IIS:\Sites\$Name" -Name physicalPath -Value $PhysicalPath
if ($AppPool) {
Set-ItemProperty "IIS:\Sites\$Name" -Name applicationPool -Value $AppPool
}
}
}
Ensure-Site -Name $SiteApi -Host $DomainApi -Path $PathApi -AppPool $AppPoolApi
Ensure-Site -Name $SiteAdmin -Host $DomainAdmin -Path $PathAdmin -AppPool ""
Ensure-Site -Name $SiteUser -Host $DomainUser -Path $PathUser -AppPool ""
Ensure-Site -Name $SiteApi -HostName $DomainApi -PhysicalPath $PathApi -AppPool $AppPoolApi
Ensure-Site -Name $SiteAdmin -HostName $DomainAdmin -PhysicalPath $PathAdmin -AppPool ""
Ensure-Site -Name $SiteUser -HostName $DomainUser -PhysicalPath $PathUser -AppPool ""
# ===================== 4. Placeholder index.html cho FE (tạm trước khi deploy thật) =====================
# ===================== 4. Placeholder index.html for FE (temporary until first real deploy) =====================
Write-Step "Placeholder index.html (pre-deploy)"
foreach ($fePath in @($PathAdmin, $PathUser)) {
$idx = Join-Path $fePath "index.html"
@ -114,7 +118,7 @@ foreach ($fePath in @($PathAdmin, $PathUser)) {
<!DOCTYPE html><html><head><meta charset="utf-8"><title>SOLUTION ERP</title></head>
<body style="font:14px sans-serif;padding:40px;text-align:center;color:#555">
<h1>SOLUTION ERP</h1>
<p>Site đã to, ch deploy first build qua Gitea CI/CD.</p>
<p>Site created, waiting for first deploy via Gitea CI/CD.</p>
</body></html>
"@ | Set-Content -Path $idx -Encoding UTF8
Write-Host " Wrote $idx"
@ -123,8 +127,8 @@ foreach ($fePath in @($PathAdmin, $PathUser)) {
}
}
# ===================== 5. web.config cho FE SPA routing =====================
Write-Step "web.config cho FE SPA fallback"
# ===================== 5. web.config for FE SPA routing =====================
Write-Step "web.config for FE SPA fallback"
$spaWebConfig = @'
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
@ -160,7 +164,7 @@ $spaWebConfig = @'
foreach ($fePath in @($PathAdmin, $PathUser)) {
Set-Content -Path (Join-Path $fePath "web.config") -Value $spaWebConfig -Encoding UTF8
}
Write-Host " Wrote SPA web.config cho admin + user"
Write-Host " Wrote SPA web.config for admin + user"
# ===================== 6. Firewall =====================
Write-Step "Firewall port 80/443"
@ -174,13 +178,14 @@ if (-not $fwExists) {
}
# ===================== 7. Recap =====================
Write-Host "`n✅ IIS setup DONE" -ForegroundColor Green
Write-Host ""
Write-Host "[OK] IIS setup DONE" -ForegroundColor Green
Write-Host " 3 sites:"
Write-Host " - $SiteApi -> $DomainApi -> $PathApi (app pool $AppPoolApi)"
Write-Host " - $SiteAdmin -> $DomainAdmin -> $PathAdmin (no app pool static)"
Write-Host " - $SiteUser -> $DomainUser -> $PathUser (no app pool static)"
Write-Host " - $SiteAdmin -> $DomainAdmin -> $PathAdmin (no app pool - static)"
Write-Host " - $SiteUser -> $DomainUser -> $PathUser (no app pool - static)"
Write-Host ""
Write-Host " Tiếp theo:"
Write-Host " 1. Chạy .\setup-ssl.ps1 để cài HTTPS cert cho 3 domain"
Write-Host " 2. Deploy first build qua Gitea Actions (push main trigger workflow)"
Write-Host " 3. Verify https://$DomainApi/health/ready 200"
Write-Host " Next:"
Write-Host " 1. Run .\setup-ssl.ps1 to install HTTPS cert for 3 domains"
Write-Host " 2. Deploy first build via Gitea Actions (push main to trigger workflow)"
Write-Host " 3. Verify https://$DomainApi/health/ready -> 200"