[Claude Code Desktop 자동 설치 환경]
- setup/CLAUDE.md: 트리거 키워드 + 설치 패키지 설명
- setup/.claude/skills/guardia-install/SKILL.md: 6단계 설치 오케스트레이터
Phase 0: 의도 파악 → Phase 1: OS 감지 → Phase 2: 사전 확인
Phase 3: 설치 실행 → Phase 4: 라이선스 발급 → Phase 5: 검증 → Phase 6: 완료보고
[통합 자동 설치 스크립트]
- setup/install_auto.sh: Linux 통합 (OS 자동 감지 ubuntu/centos/rhel)
- --license trial30|trial7|<key> 파라미터
- 설치 완료 후 GUARDiA 자동 실행 + 브라우저 자동 열기
- --test 검증 모드
- setup/install_auto.ps1: Windows 통합 (ASCII 전용, PS 5.1 호환)
- 설치 후 NSSM 서비스 자동 시작 + 브라우저 자동 열기
- -Test 파라미터로 검증 전용 실행
[라이선스 엔진 개선]
- core/license.py: generate_trial_key(days=None) 파라미터 추가
- TRIAL_DURATION_DAYS = TRIAL_DURATION_DAYS 환경변수로 조정 가능
- routers/license.py: TrialRequest.days 필드 + 30일 체험판 지원
POST /api/license/trial {"days": 30} 로 30일 발급
사용자 경험:
1. setup/ 폴더를 새 PC에 복사
2. Claude Code Desktop 열고 해당 폴더 open
3. "GUARDiA 시스템 1달 사용자로 설치해 줘" 입력
4. 자동으로 OS 감지 → 설치 → 30일 라이선스 → 브라우저 열림
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
255 lines
11 KiB
PowerShell
255 lines
11 KiB
PowerShell
# =============================================================
|
|
# GUARDiA ITSM Auto Install Script (Windows)
|
|
# Claude Code Desktop auto-invoked
|
|
# Usage: PowerShell -ExecutionPolicy Bypass -File install_auto.ps1
|
|
#
|
|
# Parameters:
|
|
# -LicenseType trial30|trial7|<key> (default: trial30)
|
|
# -Test : verification only
|
|
# -Offline : offline mode
|
|
# -SkipOllama : skip Ollama
|
|
# -SkipGitea : skip Gitea
|
|
# =============================================================
|
|
|
|
param(
|
|
[string]$LicenseType = "trial30",
|
|
[switch]$Test = $false,
|
|
[switch]$Offline = $false,
|
|
[switch]$SkipOllama = $false,
|
|
[switch]$SkipGitea = $false
|
|
)
|
|
|
|
$ErrorActionPreference = "Continue"
|
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
$LogFile = "C:\guardia_auto_install.log"
|
|
$StartTime = Get-Date
|
|
|
|
function Write-OK { param($m) Write-Host "[OK] $m" -ForegroundColor Green; Add-Content $LogFile "[OK] $m" }
|
|
function Write-Warn { param($m) Write-Host "[WARN] $m" -ForegroundColor Yellow; Add-Content $LogFile "[WARN] $m" }
|
|
function Write-Fail { param($m) Write-Host "[FAIL] $m" -ForegroundColor Red; Add-Content $LogFile "[FAIL] $m"; exit 1 }
|
|
function Write-Info { param($m) Write-Host "[INFO] $m" -ForegroundColor Cyan; Add-Content $LogFile "[INFO] $m" }
|
|
function Write-Step { param($m) Write-Host "`n=== $m ===" -ForegroundColor Cyan }
|
|
|
|
"=== GUARDiA ITSM Auto Install Start: $(Get-Date) ===" | Out-File $LogFile
|
|
|
|
# ── Admin check ───────────────────────────────────────────────
|
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
|
[Security.Principal.WindowsBuiltInRole]::Administrator
|
|
)
|
|
if (-not $isAdmin -and -not $Test) {
|
|
Write-Host "Administrator privileges required." -ForegroundColor Red
|
|
Write-Host "Run: Start-Process powershell -Verb RunAs -ArgumentList '-File $($MyInvocation.MyCommand.Path)'"
|
|
exit 1
|
|
}
|
|
|
|
# ── Verification mode ─────────────────────────────────────────
|
|
function Run-Tests {
|
|
Write-Host "=== GUARDiA ITSM Verification ===" -ForegroundColor Cyan
|
|
$pass = 0; $fail = 0
|
|
|
|
function Check-Item {
|
|
param($desc, [scriptblock]$cmd)
|
|
try {
|
|
& $cmd | Out-Null
|
|
Write-OK $desc; $script:pass++
|
|
} catch {
|
|
Write-Host "[FAIL] $desc" -ForegroundColor Red; $script:fail++
|
|
}
|
|
}
|
|
|
|
Check-Item "Java 17 (OpenJDK)" { java -version 2>&1 | Select-String "17" }
|
|
Check-Item "Python 3.11+" { python --version 2>&1 | Select-String "3\.(1[1-9])" }
|
|
Check-Item "GUARDiA service" { Get-Service "guardia-itsm" -ErrorAction Stop }
|
|
Check-Item "GUARDiA HTTP" { (Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 5).StatusCode -eq 200 }
|
|
Check-Item "GUARDiA login" {
|
|
$b = '{"username":"admin","password":"1111"}'
|
|
$r = Invoke-WebRequest "http://localhost:8001/api/auth/login" -Method POST -Body $b -ContentType "application/json" -UseBasicParsing -TimeoutSec 5
|
|
$r.StatusCode -eq 200
|
|
}
|
|
if (-not $SkipOllama) {
|
|
Check-Item "Ollama API" { (Invoke-WebRequest "http://localhost:11434/api/version" -UseBasicParsing -TimeoutSec 5).StatusCode -eq 200 }
|
|
}
|
|
if (-not $SkipGitea) {
|
|
Check-Item "Gitea HTTP" { (Invoke-WebRequest "http://localhost:3000/api/v1/version" -UseBasicParsing -TimeoutSec 5).StatusCode -eq 200 }
|
|
}
|
|
Check-Item "License status" { (Invoke-WebRequest "http://localhost:8001/api/license/status" -UseBasicParsing -TimeoutSec 5).StatusCode -eq 200 }
|
|
|
|
Write-Host ""
|
|
Write-Host "Results: Pass $pass / Fail $fail"
|
|
if ($fail -eq 0) { Write-OK "All checks passed!" } else { Write-Warn "$fail checks need attention" }
|
|
return $fail
|
|
}
|
|
|
|
# ── License issuance ──────────────────────────────────────────
|
|
function Issue-License {
|
|
param([string]$LicType)
|
|
Write-Info "Issuing license: $LicType"
|
|
|
|
# Wait for GUARDiA
|
|
$attempt = 0
|
|
while ($true) {
|
|
try { $null = Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 3; break } catch {}
|
|
Start-Sleep -Seconds 3; $attempt++
|
|
if ($attempt -ge 20) { Write-Warn "GUARDiA not responding - manual license required"; return }
|
|
}
|
|
|
|
# Login to get token
|
|
$loginBody = '{"username":"admin","password":"1111"}'
|
|
$token = ""
|
|
try {
|
|
$loginResp = Invoke-WebRequest "http://localhost:8001/api/auth/login" -Method POST -Body $loginBody -ContentType "application/json" -UseBasicParsing -TimeoutSec 10
|
|
$token = ($loginResp.Content | ConvertFrom-Json).access_token
|
|
} catch {
|
|
Write-Warn "Login failed - manual license required"
|
|
return
|
|
}
|
|
|
|
$authHeader = "Bearer $token"
|
|
$jsonHeader = "application/json"
|
|
|
|
if ($LicType -like "trial*") {
|
|
$days = if ($LicType -eq "trial7") { 7 } else { 30 }
|
|
$customer = "GUARDiA Trial $days days"
|
|
$body = "{`"customer`":`"$customer`",`"days`":$days}"
|
|
$trialOk = $false
|
|
try {
|
|
$resp = Invoke-WebRequest "http://localhost:8001/api/license/trial" -Method POST -Headers @{"Authorization"=$authHeader; "Content-Type"=$jsonHeader} -Body $body -UseBasicParsing -TimeoutSec 30
|
|
$data = $resp.Content | ConvertFrom-Json
|
|
$expDate = $data.expires_at.Substring(0, 10)
|
|
Write-OK "Trial license issued (expires: $expDate)"
|
|
$trialOk = $true
|
|
|
|
# Save to .env
|
|
$envPath = Get-ChildItem "C:\GUARDiA\itsm" -Filter ".env" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
if ($envPath -and $trialOk) {
|
|
$licKey = $data.license_key
|
|
$envContent = Get-Content $envPath.FullName -Raw
|
|
if ($envContent -match "GUARDIA_LICENSE_KEY") {
|
|
$envContent = $envContent -replace "GUARDIA_LICENSE_KEY=.*", "GUARDIA_LICENSE_KEY=$licKey"
|
|
} else {
|
|
$envContent = $envContent.TrimEnd() + "`nGUARDIA_LICENSE_KEY=$licKey`n"
|
|
}
|
|
Set-Content $envPath.FullName -Value $envContent -Encoding UTF8 -NoNewline
|
|
Write-OK "License key saved to .env"
|
|
}
|
|
} catch {
|
|
Write-Warn "Trial license failed - may already be used"
|
|
Write-Info "Manual: http://[server-ip]/license"
|
|
}
|
|
} else {
|
|
$body = "{`"license_key`":`"$LicType`"}"
|
|
try {
|
|
$null = Invoke-WebRequest "http://localhost:8001/api/license/activate" -Method POST -Headers @{"Authorization"=$authHeader; "Content-Type"=$jsonHeader} -Body $body -UseBasicParsing -TimeoutSec 30
|
|
Write-OK "License registered successfully"
|
|
} catch {
|
|
Write-Warn "License registration failed"
|
|
}
|
|
}
|
|
}
|
|
|
|
# ── Auto-start services + open browser ───────────────────────
|
|
function Start-GuardiaServices {
|
|
Write-Info "Checking GUARDiA services..."
|
|
|
|
$services = @("guardia-itsm", "tomcat9", "ollama", "redis-server")
|
|
foreach ($svc in $services) {
|
|
$s = Get-Service $svc -ErrorAction SilentlyContinue
|
|
if ($s) {
|
|
if ($s.Status -ne "Running") {
|
|
try { Start-Service $svc; Write-Info "$svc started" } catch { Write-Warn "$svc failed to start" }
|
|
} else {
|
|
Write-Info "$svc already running"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Wait for GUARDiA response (max 60s)
|
|
Write-Info "Waiting for GUARDiA response..."
|
|
$isUp = $false
|
|
for ($i=0; $i -lt 20; $i++) {
|
|
Start-Sleep -Seconds 3
|
|
try {
|
|
$r = Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 3
|
|
if ($r.StatusCode -eq 200) { $isUp = $true; break }
|
|
} catch {}
|
|
}
|
|
|
|
if ($isUp) {
|
|
Write-OK "GUARDiA ITSM is running!"
|
|
} else {
|
|
Write-Warn "GUARDiA response timeout - check manually"
|
|
return
|
|
}
|
|
|
|
# Open browser
|
|
$serverIp = ""
|
|
$ipResult = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.InterfaceAlias -notlike "*Loopback*" -and $_.PrefixOrigin -ne "WellKnown" } |
|
|
Select-Object -First 1
|
|
if ($ipResult) { $serverIp = $ipResult.IPAddress }
|
|
$url = if ($serverIp) { "http://$serverIp" } else { "http://localhost:8001" }
|
|
|
|
Write-OK "Opening browser: $url"
|
|
Start-Process $url
|
|
}
|
|
|
|
# ── Summary ───────────────────────────────────────────────────
|
|
function Print-Summary {
|
|
$serverIp = ""
|
|
$ipResult = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.InterfaceAlias -notlike "*Loopback*" -and $_.PrefixOrigin -ne "WellKnown" } |
|
|
Select-Object -First 1
|
|
if ($ipResult) { $serverIp = $ipResult.IPAddress }
|
|
|
|
$elapsed = [int](((Get-Date) - $StartTime).TotalMinutes)
|
|
$url = if ($serverIp) { "http://$serverIp" } else { "http://localhost:8001" }
|
|
|
|
Write-Host ""
|
|
Write-Host "==================================================" -ForegroundColor Green
|
|
Write-Host " GUARDiA ITSM Installation Complete!" -ForegroundColor Green
|
|
Write-Host ""
|
|
Write-Host " Time: ${elapsed}min"
|
|
Write-Host " URL: $url"
|
|
Write-Host " Account: admin / 1111"
|
|
Write-Host " License: $LicenseType"
|
|
Write-Host ""
|
|
Write-Host " Next steps:"
|
|
Write-Host " 1. Open $url -> login with admin/1111"
|
|
Write-Host " 2. Change password"
|
|
Write-Host " 3. Register servers in CMDB"
|
|
Write-Host ""
|
|
Write-Host " Verify: .\install_auto.ps1 -Test"
|
|
Write-Host " Log: $LogFile"
|
|
Write-Host "==================================================" -ForegroundColor Green
|
|
}
|
|
|
|
# ── Main ──────────────────────────────────────────────────────
|
|
if ($Test) {
|
|
$fails = Run-Tests
|
|
exit $fails
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "==================================================" -ForegroundColor Cyan
|
|
Write-Host " GUARDiA ITSM Auto Install - Windows" -ForegroundColor Cyan
|
|
Write-Host " License: $LicenseType" -ForegroundColor Cyan
|
|
Write-Host "==================================================" -ForegroundColor Cyan
|
|
Write-Host ""
|
|
|
|
Write-Step "Windows Installation"
|
|
$env:OLLAMA_INSTALL = if ($SkipOllama) { "skip" } else { "online" }
|
|
$env:INSTALL_GITEA = if ($SkipGitea) { "false" } else { "true" }
|
|
& "$ScriptDir\setup_windows.ps1"
|
|
|
|
Write-Step "License Issuance"
|
|
Issue-License -LicType $LicenseType
|
|
|
|
Write-Step "Auto Start Services"
|
|
Start-GuardiaServices
|
|
|
|
Write-Step "Installation Verification"
|
|
Run-Tests | Out-Null
|
|
|
|
Write-Step "Installation Complete"
|
|
Print-Summary
|