feat(snolla-local-admin): RESTORE DONE — local .NET admin live (6 /admin URLs)

Task A complete. Local catch-all IIS site `snolla` restored from RUVDS:
- Selective tar-copy ~100MB (excluded stale App_Data assets/galleries/themes
  8.76GB — now in MinIO), NOT the full 8.66GB.
- Web.config already pointed at mssql.kzntsv.site MoreThenCms (user snolla)
  + MinIO S3 drop-in with real keys (placeholder_count=0) — repoint not needed.
- Elevated setup script (ASCII-only, PS5.1 BOM-less-safe):
  scripts/local-snolla-admin-restore/setup-local-snolla-admin.ps1
- AppPool snolla (.NET v4.0, AppPoolIdentity, recycle@200MB), IIS site *:80,
  ACL, hosts-override (6 aliases -> 127.0.0.1), FW block inbound 80.
- Smoke GREEN: tandemmebel/labtools/labtoolspro/emspb/kupimknigi/on
  .snolla.com/admin/account/login -> 200, real MoreThenCms login form.

Unblocks Task B (on-snolla-vds-migration). MinIO upload-acceptance = manual
operator follow-up. Records: .tasks/snolla-local-admin-restore.md + STATUS.md.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-20 10:10:44 +03:00
parent d4278e79f9
commit c196964d03
4 changed files with 113 additions and 13 deletions

View File

@@ -0,0 +1,19 @@
$ErrorActionPreference='SilentlyContinue'
Write-Output "=== IIS sites ==="
Import-Module WebAdministration
Get-Website | ForEach-Object {
$b = (Get-WebBinding -Name $_.Name).bindingInformation -join ' ; '
"{0} | {1} | {2} | {3}" -f $_.Name, $_.State, $_.PhysicalPath, $b
}
Write-Output "=== C:\sites\snolla ==="
if (Test-Path 'C:\sites\snolla') {
$f = Get-ChildItem 'C:\sites\snolla' -File
"exists; top-files=" + $f.Count
$wc = 'C:\sites\snolla\Web.config'
if (Test-Path $wc) {
"Web.config size=" + (Get-Item $wc).Length
Write-Output "=== Web.config storageType / minio lines ==="
Select-String -Path $wc -Pattern 'storageType|minio\.kzntsv|FileStorage\.S3|Initial Catalog|Data Source' | ForEach-Object { $_.Line.Trim() }
} else { "Web.config MISSING" }
} else { "C:\sites\snolla MISSING" }
Write-Output "=== DONE ==="

View File

@@ -0,0 +1,75 @@
# setup-local-snolla-admin.ps1 - restore local catch-all IIS site 'snolla' (admin for tirazh + on.snolla.com)
# RUN FROM elevated PowerShell: Set-ExecutionPolicy -Scope Process Bypass; & 'C:\Users\vitya\projects\.admin\scripts\local-snolla-admin-restore\setup-local-snolla-admin.ps1'
# Source: C:\sites\snolla\ already copied from RUVDS (selective ~100MB, Web.config -> mssql.kzntsv.site + MinIO S3).
$logPath = 'C:\Users\vitya\projects\.admin\.tmp\setup-log.txt'
Start-Transcript -Path $logPath -Force | Out-Null
$ErrorActionPreference = 'Stop'
try {
Import-Module WebAdministration
$siteName = 'snolla'
$poolName = 'snolla'
$physPath = 'C:\sites\snolla'
$aliases = @('tandemmebel.snolla.com','labtools.snolla.com','labtoolspro.snolla.com','emspb.snolla.com','kupimknigi.snolla.com','on.snolla.com')
Write-Host "== 1. AppPool $poolName =="
if (Test-Path "IIS:\AppPools\$poolName") {
Write-Host " exists, ensuring config"
} else {
New-WebAppPool -Name $poolName | Out-Null
}
Set-ItemProperty "IIS:\AppPools\$poolName" -Name managedRuntimeVersion -Value 'v4.0'
Set-ItemProperty "IIS:\AppPools\$poolName" -Name processModel.identityType -Value 'ApplicationPoolIdentity'
Set-ItemProperty "IIS:\AppPools\$poolName" -Name recycling.periodicRestart.memory -Value 200
Write-Host "== 2. IIS site $siteName (catch-all *:80) =="
if (Test-Path "IIS:\Sites\$siteName") {
Write-Host " exists - removing to recreate cleanly"
Remove-Website -Name $siteName
}
# catch-all HTTP on *:80 (no HostHeader = matches any Host header)
New-Website -Name $siteName -PhysicalPath $physPath -ApplicationPool $poolName -Port 80 -Force | Out-Null
Set-ItemProperty "IIS:\Sites\$siteName" -Name physicalPath -Value $physPath
Write-Host "== 3. ACL: IIS AppPool\$poolName (OI)(CI)(M) on $physPath =="
icacls $physPath /grant "IIS AppPool\${poolName}:(OI)(CI)(M)" /T /C | Out-Null
Write-Host "== 4. hosts-override (127.0.0.1 aliases) =="
$hostsFile = "$env:windir\System32\drivers\etc\hosts"
$hostsContent = Get-Content $hostsFile -Raw -ErrorAction SilentlyContinue
$marker = '# snolla-local-admin'
if ($hostsContent -notmatch [regex]::Escape($marker)) {
$line = "`r`n$marker`r`n127.0.0.1 $($aliases -join ' ')`r`n"
Add-Content -Path $hostsFile -Value $line -Encoding ASCII
Write-Host " added hosts entries"
} else {
Write-Host " hosts entries already present (marker found)"
}
Write-Host "== 5. FW: block inbound TCP 80 (local-only guard; loopback not filtered) =="
$fwName = 'block-inbound-80-snolla-local'
if (-not (Get-NetFirewallRule -DisplayName $fwName -ErrorAction SilentlyContinue)) {
New-NetFirewallRule -DisplayName $fwName -Direction Inbound -Protocol TCP -LocalPort 80 -Action Block -Profile Any | Out-Null
Write-Host " block rule added"
} else { Write-Host " block rule already present" }
Write-Host "== 6. Start =="
Start-WebAppPool $poolName
Start-Website $siteName
Start-Sleep -Seconds 3
Write-Host " pool state: $((Get-WebAppPoolState $poolName).Text)"
Write-Host " site state: $((Get-WebsiteState $siteName).Text)"
Write-Host "== 7. Smoke (curl --noproxy bypasses VPN-proxy localhost swallow) =="
foreach ($a in $aliases) {
$code = & curl.exe --noproxy '*' -s -o NUL -w "%{http_code}" -H "Host: $a" "http://127.0.0.1/admin/account/login" 2>$null
Write-Host " http://$a/admin/account/login -> $code"
}
Write-Host "== DONE - open http://tandemmebel.snolla.com/admin in browser =="
Write-Host "(if login form not 200 - check C:\Logs\snolla\log*.txt and eventvwr IIS)"
} catch {
Write-Host "FATAL: $_"
Write-Host $_.ScriptStackTrace
}
Stop-Transcript | Out-Null