fix(setup): setup_windows.ps1 PowerShell 5.1 완전 호환 재작성
- 한글 제거 -> ASCII 전용 (PS5.1은 BOM없는 UTF-8을 CP949로 읽어 파싱 오류 발생) - ?. null-conditional 연산자 제거 -> 전통적 if/else로 교체 - 줄 연속 백틱 제거 -> 단일 라인으로 변경 - psql 단일인용부호 이슈 -> [char]39 + tmpSql 파일 방식으로 우회 - Path 환경변수 연결 -> + 연산자 방식으로 변경 - 구문 오류 0개 확인 완료 (ParseFile 검증) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d196886752
commit
d3e13d2fc2
@ -1,9 +1,14 @@
|
|||||||
# ==============================================================
|
# ==============================================================
|
||||||
# GUARDiA ITSM 설치 스크립트 — Windows Server 2019/2022
|
# GUARDiA ITSM Setup Script - Windows Server 2019/2022
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
# 전제조건: 순수 Windows Server OS (PowerShell 5.1+)
|
# Requirements: Windows Server OS, PowerShell 5.1+
|
||||||
# 실행 방법: PowerShell -ExecutionPolicy Bypass -File setup_windows.ps1
|
# Usage: PowerShell -ExecutionPolicy Bypass -File setup_windows.ps1
|
||||||
# 설치 테스트: .\setup_windows.ps1 -Test
|
# Test : .\setup_windows.ps1 -Test
|
||||||
|
# Env vars (offline):
|
||||||
|
# TOMCAT_VER = 9.0.98 (default)
|
||||||
|
# TOMCAT_MIRROR = http://internal-mirror/...
|
||||||
|
# OLLAMA_INSTALL = online|offline|skip
|
||||||
|
# OLLAMA_BIN_PATH = path to OllamaSetup.exe
|
||||||
# ==============================================================
|
# ==============================================================
|
||||||
|
|
||||||
param(
|
param(
|
||||||
@ -23,13 +28,15 @@ function Write-Info { param($msg) Write-Host " $msg" }
|
|||||||
Start-Transcript -Path $LogFile -Append | Out-Null
|
Start-Transcript -Path $LogFile -Append | Out-Null
|
||||||
|
|
||||||
Write-Host "=================================================="
|
Write-Host "=================================================="
|
||||||
Write-Host " GUARDiA ITSM 설치 — Windows Server"
|
Write-Host " GUARDiA ITSM Setup - Windows Server"
|
||||||
Write-Host " 시작: $(Get-Date)"
|
Write-Host " Start: $(Get-Date)"
|
||||||
Write-Host "=================================================="
|
Write-Host "=================================================="
|
||||||
|
|
||||||
# ── 테스트 모드 ─────────────────────────────────────────────
|
# ==============================================================
|
||||||
|
# TEST MODE
|
||||||
|
# ==============================================================
|
||||||
if ($Test) {
|
if ($Test) {
|
||||||
Write-Host "=== 설치 검증 모드 ==="
|
Write-Host "=== Installation Verification Mode ==="
|
||||||
$pass = 0; $fail = 0
|
$pass = 0; $fail = 0
|
||||||
|
|
||||||
function Check-Item {
|
function Check-Item {
|
||||||
@ -42,73 +49,90 @@ if ($Test) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Check-Item "Python 3.11+" { python --version 2>&1 | Select-String "3\.(1[1-9]|[2-9]\d)" }
|
Check-Item "Python 3.11+" {
|
||||||
Check-Item "PostgreSQL 응답" { pg_isready -q }
|
$v = python --version 2>&1
|
||||||
Check-Item "Redis 응답" { redis-cli ping }
|
if ($v -notmatch "3\.(1[1-9]|[2-9]\d)") { throw "Version mismatch: $v" }
|
||||||
Check-Item "Java 17 (OpenJDK)" { java -version 2>$null }
|
|
||||||
Check-Item "Tomcat 9 서비스" { $s = Get-Service "tomcat9" -ErrorAction Stop; if ($s.Status -ne "Running") { throw "" } }
|
|
||||||
Check-Item "Tomcat HTTP" { $r = Invoke-WebRequest "http://localhost:8080/" -UseBasicParsing -TimeoutSec 5; if ($r.StatusCode -ne 200) { throw "" } }
|
|
||||||
Check-Item "NSSM 서비스 등록" { Get-Service "guardia-itsm" -ErrorAction Stop }
|
|
||||||
Check-Item "GUARDiA 서비스 실행" {
|
|
||||||
$s = Get-Service "guardia-itsm"
|
|
||||||
if ($s.Status -ne "Running") { throw "서비스 상태: $($s.Status)" }
|
|
||||||
}
|
}
|
||||||
Check-Item "GUARDiA HTTP 응답" {
|
Check-Item "Java 17 (OpenJDK)" {
|
||||||
|
$v = java -version 2>&1
|
||||||
|
if ("$v" -notmatch "17|18|19|20|21") { throw "Java 17+ required" }
|
||||||
|
}
|
||||||
|
Check-Item "PostgreSQL ready" { pg_isready -q }
|
||||||
|
Check-Item "Redis ping" { redis-cli ping }
|
||||||
|
Check-Item "Tomcat 9 service" {
|
||||||
|
$s = Get-Service "tomcat9" -ErrorAction Stop
|
||||||
|
if ($s.Status -ne "Running") { throw "Status: $($s.Status)" }
|
||||||
|
}
|
||||||
|
Check-Item "Tomcat HTTP" {
|
||||||
|
$r = Invoke-WebRequest "http://localhost:8080/" -UseBasicParsing -TimeoutSec 5
|
||||||
|
if ($r.StatusCode -ne 200) { throw "HTTP $($r.StatusCode)" }
|
||||||
|
}
|
||||||
|
Check-Item "Ollama API" {
|
||||||
|
$r = Invoke-WebRequest "http://localhost:11434/api/version" -UseBasicParsing -TimeoutSec 5
|
||||||
|
if ($r.StatusCode -ne 200) { throw "Ollama not responding" }
|
||||||
|
}
|
||||||
|
Check-Item "Ollama model exists" {
|
||||||
|
$out = ollama list 2>&1
|
||||||
|
if ("$out" -notmatch "\S") { throw "No models found" }
|
||||||
|
}
|
||||||
|
Check-Item "guardia-itsm service" { Get-Service "guardia-itsm" -ErrorAction Stop }
|
||||||
|
Check-Item "GUARDiA HTTP" {
|
||||||
$r = Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 10
|
$r = Invoke-WebRequest "http://localhost:8001/" -UseBasicParsing -TimeoutSec 10
|
||||||
if ($r.StatusCode -ne 200) { throw "HTTP $($r.StatusCode)" }
|
if ($r.StatusCode -ne 200) { throw "HTTP $($r.StatusCode)" }
|
||||||
}
|
}
|
||||||
Check-Item "GUARDiA 로그인 API" {
|
Check-Item "GUARDiA login API" {
|
||||||
$body = '{"username":"admin","password":"1111"}'
|
$body = '{"username":"admin","password":"1111"}'
|
||||||
$r = Invoke-WebRequest "http://localhost:8001/api/auth/login" -Method POST `
|
$r = Invoke-WebRequest "http://localhost:8001/api/auth/login" `
|
||||||
-ContentType "application/json" -Body $body -UseBasicParsing -TimeoutSec 10
|
-Method POST -ContentType "application/json" -Body $body `
|
||||||
if ($r.StatusCode -ne 200) { throw "로그인 실패 ($($r.StatusCode))" }
|
-UseBasicParsing -TimeoutSec 10
|
||||||
|
if ($r.StatusCode -ne 200) { throw "Login failed ($($r.StatusCode))" }
|
||||||
}
|
}
|
||||||
Check-Item "Python UTF-8 인코딩" {
|
Check-Item "Python UTF-8 encoding" {
|
||||||
$env:PYTHONIOENCODING = "utf-8"
|
$env:PYTHONIOENCODING = "utf-8"
|
||||||
$out = & python -c "print('OK')" 2>&1
|
$out = & python -c "print('OK')" 2>&1
|
||||||
if ("$out" -notmatch "OK") { throw "인코딩 오류: $out" }
|
if ("$out" -notmatch "OK") { throw "Encoding error: $out" }
|
||||||
}
|
}
|
||||||
Check-Item "Ollama 실행" {
|
Check-Item "Nginx config" { nginx -t 2>&1 }
|
||||||
$r = Invoke-WebRequest "http://localhost:11434/api/version" -UseBasicParsing -TimeoutSec 5
|
|
||||||
if ($r.StatusCode -ne 200) { throw "Ollama 응답 없음" }
|
|
||||||
}
|
|
||||||
Check-Item "Ollama 모델 존재" {
|
|
||||||
$out = ollama list 2>&1
|
|
||||||
if ($out -notmatch "\S") { throw "모델 없음" }
|
|
||||||
}
|
|
||||||
Check-Item "Nginx 설정" { nginx -t 2>&1 }
|
|
||||||
|
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "검증 결과: 성공 $pass / 실패 $fail"
|
Write-Host "Results: Pass $pass / Fail $fail"
|
||||||
if ($fail -eq 0) {
|
if ($fail -eq 0) {
|
||||||
Write-OK "모든 검사 통과 — GUARDiA ITSM 정상 설치됨"
|
Write-OK "All checks passed - GUARDiA ITSM installed successfully"
|
||||||
} else {
|
} else {
|
||||||
Write-Fail "일부 검사 실패 — 로그 확인: $LogFile"
|
Write-Fail "Some checks failed - see log: $LogFile"
|
||||||
}
|
}
|
||||||
Stop-Transcript | Out-Null
|
Stop-Transcript | Out-Null
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── 관리자 권한 확인 ────────────────────────────────────────
|
# ==============================================================
|
||||||
|
# Admin check
|
||||||
|
# ==============================================================
|
||||||
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
||||||
[Security.Principal.WindowsBuiltInRole]::Administrator
|
[Security.Principal.WindowsBuiltInRole]::Administrator
|
||||||
)
|
)
|
||||||
if (-not $isAdmin) { Write-Fail "관리자 권한으로 실행하세요 (우클릭 → 관리자로 실행)" }
|
if (-not $isAdmin) { Write-Fail "Run as Administrator (right-click -> Run as administrator)" }
|
||||||
|
|
||||||
# ── Chocolatey 패키지 관리자 ────────────────────────────────
|
# ==============================================================
|
||||||
|
# [1/10] Chocolatey
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[1/8] Chocolatey 패키지 관리자 설치..."
|
Write-Host "[1/10] Chocolatey package manager..."
|
||||||
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
|
if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
|
||||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||||||
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
$mp = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
|
$up = [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||||
|
$env:Path = $mp + ";" + $up
|
||||||
}
|
}
|
||||||
Write-OK "Chocolatey 준비 완료"
|
Write-OK "Chocolatey ready"
|
||||||
|
|
||||||
# ── 1. 필수 패키지 설치 ──────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [2/10] Required packages: Python, Java, PostgreSQL, Redis, Nginx, NSSM
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[2/10] 필수 패키지 설치 (Python, Java, PostgreSQL, Redis, Nginx, NSSM)..."
|
Write-Host "[2/10] Installing required packages..."
|
||||||
|
|
||||||
$packages = @(
|
$packages = @(
|
||||||
"python --version=3.11.9",
|
"python --version=3.11.9",
|
||||||
@ -122,33 +146,42 @@ $packages = @(
|
|||||||
|
|
||||||
foreach ($pkg in $packages) {
|
foreach ($pkg in $packages) {
|
||||||
$name = $pkg.Split(" ")[0]
|
$name = $pkg.Split(" ")[0]
|
||||||
Write-Host " 설치 중: $name"
|
Write-Host " Installing: $name"
|
||||||
choco install $pkg -y --no-progress 2>&1 | Out-Null
|
choco install $pkg -y --no-progress 2>&1 | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
# PATH 갱신
|
$mp2 = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
|
$up2 = [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||||
|
$env:Path = $mp2 + ";" + $up2
|
||||||
|
|
||||||
# JAVA_HOME 설정
|
# JAVA_HOME (PowerShell 5.1 compatible - no ?. operator)
|
||||||
$javaHome = (Get-ChildItem "C:\Program Files\Eclipse Adoptium" -ErrorAction SilentlyContinue | Sort-Object Name -Descending | Select-Object -First 1)?.FullName
|
$javaHome = ""
|
||||||
|
$adoptiumItems = Get-ChildItem "C:\Program Files\Eclipse Adoptium" -ErrorAction SilentlyContinue |
|
||||||
|
Sort-Object Name -Descending | Select-Object -First 1
|
||||||
|
if ($adoptiumItems) { $javaHome = $adoptiumItems.FullName }
|
||||||
if (-not $javaHome) {
|
if (-not $javaHome) {
|
||||||
$javaHome = (Get-ChildItem "C:\Program Files\Java" -Filter "jdk*17*" -ErrorAction SilentlyContinue | Select-Object -First 1)?.FullName
|
$javaItems = Get-ChildItem "C:\Program Files\Java" -Filter "jdk*17*" -ErrorAction SilentlyContinue |
|
||||||
|
Select-Object -First 1
|
||||||
|
if ($javaItems) { $javaHome = $javaItems.FullName }
|
||||||
}
|
}
|
||||||
if (-not $javaHome) {
|
if (-not $javaHome) {
|
||||||
$javaHome = (Get-Command java -ErrorAction SilentlyContinue)?.Source | Split-Path | Split-Path
|
$javaCmd = Get-Command java -ErrorAction SilentlyContinue
|
||||||
|
if ($javaCmd) { $javaHome = Split-Path (Split-Path $javaCmd.Source) }
|
||||||
}
|
}
|
||||||
if ($javaHome) {
|
if ($javaHome) {
|
||||||
[System.Environment]::SetEnvironmentVariable("JAVA_HOME", $javaHome, "Machine")
|
[System.Environment]::SetEnvironmentVariable("JAVA_HOME", $javaHome, "Machine")
|
||||||
$env:JAVA_HOME = $javaHome
|
$env:JAVA_HOME = $javaHome
|
||||||
Write-OK "OpenJDK 17 설치 완료 (JAVA_HOME=$javaHome)"
|
Write-OK "OpenJDK 17 ready (JAVA_HOME=$javaHome)"
|
||||||
} else {
|
} else {
|
||||||
Write-Warn "JAVA_HOME을 찾을 수 없음 — 수동 설정 필요"
|
Write-Warn "JAVA_HOME not found - set manually"
|
||||||
}
|
}
|
||||||
Write-OK "필수 패키지 설치 완료"
|
Write-OK "Packages installed"
|
||||||
|
|
||||||
# ── 2. Tomcat 9 설치 ────────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [3/10] Tomcat 9
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[3/10] Tomcat 9 설치..."
|
Write-Host "[3/10] Installing Tomcat 9..."
|
||||||
|
|
||||||
$TomcatVer = if ($env:TOMCAT_VER) { $env:TOMCAT_VER } else { "9.0.98" }
|
$TomcatVer = if ($env:TOMCAT_VER) { $env:TOMCAT_VER } else { "9.0.98" }
|
||||||
$TomcatHome = "C:\app\tomcat"
|
$TomcatHome = "C:\app\tomcat"
|
||||||
@ -159,53 +192,62 @@ $TomcatMirror = if ($env:TOMCAT_MIRROR) { $env:TOMCAT_MIRROR } else {
|
|||||||
if (-not (Test-Path "$TomcatHome\bin\startup.bat")) {
|
if (-not (Test-Path "$TomcatHome\bin\startup.bat")) {
|
||||||
$tarName = "apache-tomcat-$TomcatVer.zip"
|
$tarName = "apache-tomcat-$TomcatVer.zip"
|
||||||
$tarUrl = "$TomcatMirror/$tarName"
|
$tarUrl = "$TomcatMirror/$tarName"
|
||||||
Write-Host " 다운로드: $tarUrl"
|
Write-Host " Downloading: $tarUrl"
|
||||||
try {
|
try {
|
||||||
Invoke-WebRequest $tarUrl -OutFile "$env:TEMP\$tarName" -TimeoutSec 120 -UseBasicParsing
|
Invoke-WebRequest $tarUrl -OutFile "$env:TEMP\$tarName" -TimeoutSec 120 -UseBasicParsing
|
||||||
Expand-Archive "$env:TEMP\$tarName" -DestinationPath "C:\app" -Force
|
Expand-Archive "$env:TEMP\$tarName" -DestinationPath "C:\app" -Force
|
||||||
Rename-Item "C:\app\apache-tomcat-$TomcatVer" $TomcatHome -ErrorAction SilentlyContinue
|
$extractedDir = "C:\app\apache-tomcat-$TomcatVer"
|
||||||
if (-not (Test-Path $TomcatHome)) {
|
if (Test-Path $extractedDir) {
|
||||||
Move-Item "C:\app\apache-tomcat-$TomcatVer" $TomcatHome
|
if (Test-Path $TomcatHome) { Remove-Item $TomcatHome -Recurse -Force }
|
||||||
|
Rename-Item $extractedDir $TomcatHome
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
Write-Warn "Tomcat 다운로드 실패: $_"
|
Write-Warn "Tomcat download failed: $_ - set TOMCAT_MIRROR to internal mirror"
|
||||||
Write-Warn "TOMCAT_MIRROR 환경변수를 내부 미러로 설정하거나 수동 설치하세요."
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host " Tomcat이 이미 설치되어 있음: $TomcatHome"
|
Write-Info "Tomcat already installed: $TomcatHome"
|
||||||
}
|
}
|
||||||
|
|
||||||
# opsagent 계정 추가 (GUARDiA Manager 원격 제어용)
|
# Add opsagent to Tomcat Manager
|
||||||
$TomcatUsersXml = "$TomcatHome\conf\tomcat-users.xml"
|
$TomcatUsersXml = "$TomcatHome\conf\tomcat-users.xml"
|
||||||
if ((Test-Path $TomcatUsersXml) -and -not (Select-String "opsagent" $TomcatUsersXml -Quiet)) {
|
if (Test-Path $TomcatUsersXml) {
|
||||||
(Get-Content $TomcatUsersXml) -replace '</tomcat-users>', @"
|
$content = Get-Content $TomcatUsersXml -Raw
|
||||||
<role rolename="manager-script"/>
|
if ($content -notmatch "opsagent") {
|
||||||
<role rolename="manager-jmx"/>
|
$addEntry = ' <role rolename="manager-script"/>' + "`r`n" +
|
||||||
<user username="opsagent" password="Opsagent@guardia!" roles="manager-script,manager-jmx"/>
|
' <role rolename="manager-jmx"/>' + "`r`n" +
|
||||||
</tomcat-users>
|
' <user username="opsagent" password="Opsagent@guardia!" roles="manager-script,manager-jmx"/>' + "`r`n" +
|
||||||
"@ | Set-Content $TomcatUsersXml -Encoding utf8
|
'</tomcat-users>'
|
||||||
|
$newContent = $content -replace '</tomcat-users>', $addEntry
|
||||||
|
Set-Content $TomcatUsersXml -Value $newContent -Encoding UTF8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# NSSM으로 Tomcat 9 Windows 서비스 등록
|
# Register Tomcat as Windows service via NSSM
|
||||||
$tcSvc = "tomcat9"
|
$tcSvc = "tomcat9"
|
||||||
try { nssm stop $tcSvc 2>$null; nssm remove $tcSvc confirm 2>$null } catch {}
|
try { nssm stop $tcSvc 2>$null } catch {}
|
||||||
nssm install $tcSvc "$TomcatHome\bin\tomcat9.exe" 2>$null
|
try { nssm remove $tcSvc confirm 2>$null } catch {}
|
||||||
if ($LASTEXITCODE -ne 0) {
|
|
||||||
# tomcat9.exe 없으면 startup.bat 방식
|
$tcExe = "$TomcatHome\bin\tomcat9.exe"
|
||||||
nssm install $tcSvc "cmd"
|
if (Test-Path $tcExe) {
|
||||||
nssm set $tcSvc AppParameters "/c $TomcatHome\bin\startup.bat"
|
nssm install $tcSvc $tcExe
|
||||||
|
} else {
|
||||||
|
nssm install $tcSvc "cmd.exe"
|
||||||
|
$batPath = "$TomcatHome\bin\startup.bat"
|
||||||
|
nssm set $tcSvc AppParameters ("/c `"$batPath`"")
|
||||||
}
|
}
|
||||||
nssm set $tcSvc AppDirectory $TomcatHome
|
nssm set $tcSvc AppDirectory $TomcatHome
|
||||||
nssm set $tcSvc AppEnvironmentExtra "JAVA_HOME=$env:JAVA_HOME CATALINA_HOME=$TomcatHome"
|
nssm set $tcSvc AppEnvironmentExtra ("JAVA_HOME=" + $env:JAVA_HOME + " CATALINA_HOME=" + $TomcatHome)
|
||||||
nssm set $tcSvc Start SERVICE_AUTO_START
|
nssm set $tcSvc Start SERVICE_AUTO_START
|
||||||
nssm set $tcSvc AppStdout "C:\guardia\logs\tomcat9.log"
|
|
||||||
New-Item -ItemType Directory -Force "C:\guardia\logs" | Out-Null
|
New-Item -ItemType Directory -Force "C:\guardia\logs" | Out-Null
|
||||||
|
nssm set $tcSvc AppStdout "C:\guardia\logs\tomcat9.log"
|
||||||
nssm start $tcSvc
|
nssm start $tcSvc
|
||||||
Write-OK "Tomcat 9 서비스 등록 완료 (포트 8080)"
|
Write-OK "Tomcat 9 service registered (port 8080)"
|
||||||
|
|
||||||
# ── 2(b). Python 가상환경 ──────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [4/10] Python virtual environment
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[4/10] Python 가상환경 설정..."
|
Write-Host "[4/10] Python virtual environment..."
|
||||||
$venvPath = "C:\guardia\venv"
|
$venvPath = "C:\guardia\venv"
|
||||||
if (-not (Test-Path $venvPath)) {
|
if (-not (Test-Path $venvPath)) {
|
||||||
python -m venv $venvPath
|
python -m venv $venvPath
|
||||||
@ -213,59 +255,83 @@ if (-not (Test-Path $venvPath)) {
|
|||||||
$pip = "$venvPath\Scripts\pip.exe"
|
$pip = "$venvPath\Scripts\pip.exe"
|
||||||
& $pip install --upgrade pip -q
|
& $pip install --upgrade pip -q
|
||||||
& $pip install -r "$GuardiaRoot\itsm\requirements.txt" -q
|
& $pip install -r "$GuardiaRoot\itsm\requirements.txt" -q
|
||||||
Write-OK "Python 패키지 설치 완료"
|
Write-OK "Python packages installed"
|
||||||
|
|
||||||
# ── 3. PostgreSQL 초기화 ────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [5/10] PostgreSQL
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[4/8] PostgreSQL 초기화..."
|
Write-Host "[5/10] PostgreSQL setup..."
|
||||||
|
$pgBin = ""
|
||||||
|
$pgVersionDirs = Get-ChildItem "C:\Program Files\PostgreSQL" -Directory -ErrorAction SilentlyContinue |
|
||||||
|
Sort-Object Name -Descending | Select-Object -First 1
|
||||||
|
if ($pgVersionDirs) {
|
||||||
|
$pgBin = $pgVersionDirs.FullName + "\bin"
|
||||||
|
}
|
||||||
|
if (-not $pgBin -or -not (Test-Path $pgBin)) {
|
||||||
$pgBin = "C:\Program Files\PostgreSQL\16\bin"
|
$pgBin = "C:\Program Files\PostgreSQL\16\bin"
|
||||||
if (-not (Test-Path $pgBin)) {
|
|
||||||
$pgBin = Get-ChildItem "C:\Program Files\PostgreSQL" -Directory | Sort-Object Name -Descending | Select-Object -First 1 | ForEach-Object { "$($_.FullName)\bin" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$env:PGPASSWORD = "postgres"
|
$env:PGPASSWORD = "postgres"
|
||||||
# DB/사용자 생성
|
$psql = "$pgBin\psql.exe"
|
||||||
& "$pgBin\psql.exe" -U postgres -c "CREATE USER guardia WITH PASSWORD 'guardia_secure_pw';" 2>$null
|
# Write SQL to temp file to avoid quoting issues
|
||||||
& "$pgBin\psql.exe" -U postgres -c "CREATE DATABASE guardia OWNER guardia;" 2>$null
|
$tmpSql = "$env:TEMP\guardia_pg_setup.sql"
|
||||||
Write-OK "PostgreSQL 설정 완료"
|
$q = [char]39 # single quote
|
||||||
|
$sqlLines = "CREATE USER guardia WITH PASSWORD " + $q + "guardia_secure_pw" + $q + ";" + "`n"
|
||||||
|
$sqlLines += "CREATE DATABASE guardia OWNER guardia;" + "`n"
|
||||||
|
Set-Content $tmpSql -Value $sqlLines -Encoding ASCII
|
||||||
|
try { & $psql -U postgres -f $tmpSql 2>$null } catch {}
|
||||||
|
Remove-Item $tmpSql -ErrorAction SilentlyContinue
|
||||||
|
Write-OK "PostgreSQL setup complete"
|
||||||
|
|
||||||
# ── 4. Redis 서비스 등록 ────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [6/10] Redis
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[5/10] Redis 서비스 등록..."
|
Write-Host "[6/10] Redis service..."
|
||||||
$redisExe = (Get-Command redis-server -ErrorAction SilentlyContinue)?.Source
|
$redisCmd = Get-Command redis-server -ErrorAction SilentlyContinue
|
||||||
if ($redisExe) {
|
if ($redisCmd) {
|
||||||
nssm install redis-server $redisExe 2>$null
|
$redisExe = $redisCmd.Source
|
||||||
nssm start redis-server 2>$null
|
try { nssm stop redis-server 2>$null } catch {}
|
||||||
|
try { nssm remove redis-server confirm 2>$null } catch {}
|
||||||
|
nssm install redis-server $redisExe
|
||||||
|
nssm start redis-server
|
||||||
}
|
}
|
||||||
Write-OK "Redis 완료"
|
Write-OK "Redis ready"
|
||||||
|
|
||||||
# ── 5. 환경 설정 파일 ───────────────────────────────────────
|
# ==============================================================
|
||||||
|
# [7/10] Environment file (.env)
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[6/10] 환경 설정 파일 생성..."
|
Write-Host "[7/10] Creating .env file..."
|
||||||
$envFile = "$GuardiaRoot\itsm\.env"
|
$envFile = "$GuardiaRoot\itsm\.env"
|
||||||
if (-not (Test-Path $envFile)) {
|
if (-not (Test-Path $envFile)) {
|
||||||
@"
|
$envLines = @(
|
||||||
DATABASE_URL=postgresql+asyncpg://guardia:guardia_secure_pw@localhost:5432/guardia
|
"DATABASE_URL=postgresql+asyncpg://guardia:guardia_secure_pw@localhost:5432/guardia",
|
||||||
SECRET_KEY=change_this_secret_key_in_production_min_32chars
|
"SECRET_KEY=change_this_secret_key_in_production_min_32chars",
|
||||||
ALGORITHM=HS256
|
"ALGORITHM=HS256",
|
||||||
ACCESS_TOKEN_EXPIRE_MINUTES=480
|
"ACCESS_TOKEN_EXPIRE_MINUTES=480",
|
||||||
REDIS_URL=redis://localhost:6379/0
|
"REDIS_URL=redis://localhost:6379/0",
|
||||||
OLLAMA_BASE_URL=http://localhost:11434
|
"OLLAMA_BASE_URL=http://localhost:11434",
|
||||||
GUARDIA_LLM_MODEL=llama3.1:8b
|
"GUARDIA_LLM_MODEL=llama3.1:8b",
|
||||||
MESSENGER_BASE_URL=http://localhost:8002
|
"MESSENGER_BASE_URL=http://localhost:8002",
|
||||||
MESSENGER_OPS_ROOM=ops
|
"MESSENGER_OPS_ROOM=ops",
|
||||||
"@ | Out-File -FilePath $envFile -Encoding utf8
|
"CATALINA_HOME=C:\app\tomcat"
|
||||||
Write-Warn ".env 생성됨 — SECRET_KEY를 변경하세요: $envFile"
|
)
|
||||||
|
Set-Content $envFile -Value ($envLines -join "`r`n") -Encoding UTF8
|
||||||
|
Write-Warn ".env created - change SECRET_KEY before production use: $envFile"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── 6. DB 초기화 (스키마 불일치 자동 감지·복구) ────────────────────────
|
# ==============================================================
|
||||||
|
# [8/10] DB initialization (auto schema repair)
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[7/10] DB 초기화..."
|
Write-Host "[8/10] DB initialization..."
|
||||||
|
|
||||||
# 포트 8001 기존 프로세스 종료 (업그레이드 시 충돌 방지)
|
$portProc = Get-NetTCPConnection -LocalPort 8001 -State Listen -ErrorAction SilentlyContinue |
|
||||||
$portProc = Get-NetTCPConnection -LocalPort 8001 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
|
Select-Object -First 1
|
||||||
if ($portProc) {
|
if ($portProc) {
|
||||||
Write-Warn "포트 8001 사용 중 (PID $($portProc.OwningProcess)) — 종료..."
|
Write-Warn "Port 8001 in use (PID $($portProc.OwningProcess)) - stopping..."
|
||||||
Stop-Process -Id $portProc.OwningProcess -Force -ErrorAction SilentlyContinue
|
Stop-Process -Id $portProc.OwningProcess -Force -ErrorAction SilentlyContinue
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
}
|
}
|
||||||
@ -276,130 +342,136 @@ $env:PYTHONUNBUFFERED = "1"
|
|||||||
$dbResult = & "$venvPath\Scripts\python.exe" tools\db_init.py --force 2>&1
|
$dbResult = & "$venvPath\Scripts\python.exe" tools\db_init.py --force 2>&1
|
||||||
$dbResult | ForEach-Object { Write-Host " $_" }
|
$dbResult | ForEach-Object { Write-Host " $_" }
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-Fail "DB 초기화 실패 — 로그를 확인하세요"
|
Write-Fail "DB init failed - check log: $LogFile"
|
||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Write-OK "DB 초기화 완료"
|
Write-OK "DB initialized"
|
||||||
|
|
||||||
# ── 7. NSSM Windows 서비스 등록 ─────────────────────────────
|
# ==============================================================
|
||||||
|
# [9/10] GUARDiA ITSM Windows service (NSSM)
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[8/10] Windows 서비스 등록 (NSSM)..."
|
Write-Host "[9/10] GUARDiA ITSM service..."
|
||||||
|
|
||||||
$uvicorn = "$venvPath\Scripts\uvicorn.exe"
|
$uvicorn = "$venvPath\Scripts\uvicorn.exe"
|
||||||
$svcName = "guardia-itsm"
|
$svcName = "guardia-itsm"
|
||||||
|
|
||||||
# 기존 서비스 중지 및 제거 (업그레이드)
|
|
||||||
try { nssm stop $svcName 2>$null; Start-Sleep -Seconds 2 } catch {}
|
try { nssm stop $svcName 2>$null; Start-Sleep -Seconds 2 } catch {}
|
||||||
try { nssm remove $svcName confirm 2>$null } catch {}
|
try { nssm remove $svcName confirm 2>$null } catch {}
|
||||||
|
|
||||||
nssm install $svcName $uvicorn
|
nssm install $svcName $uvicorn
|
||||||
nssm set $svcName AppParameters "main:app --host 0.0.0.0 --port 8001 --workers 4"
|
nssm set $svcName AppParameters "main:app --host 0.0.0.0 --port 8001 --workers 4"
|
||||||
nssm set $svcName AppDirectory "$GuardiaRoot\itsm"
|
nssm set $svcName AppDirectory "$GuardiaRoot\itsm"
|
||||||
# PYTHONIOENCODING=utf-8 필수 — Windows 기본 cp949에서 한글 print 오류 방지
|
$extraEnv = "PATH=" + $venvPath + "\Scripts;" + $env:PATH + " PYTHONIOENCODING=utf-8 PYTHONUNBUFFERED=1"
|
||||||
nssm set $svcName AppEnvironmentExtra "PATH=$venvPath\Scripts;$env:PATH PYTHONIOENCODING=utf-8 PYTHONUNBUFFERED=1"
|
nssm set $svcName AppEnvironmentExtra $extraEnv
|
||||||
nssm set $svcName Start SERVICE_AUTO_START
|
nssm set $svcName Start SERVICE_AUTO_START
|
||||||
nssm set $svcName AppStdout "C:\guardia\logs\guardia-itsm.log"
|
nssm set $svcName AppStdout "C:\guardia\logs\guardia-itsm.log"
|
||||||
nssm set $svcName AppStderr "C:\guardia\logs\guardia-itsm-err.log"
|
nssm set $svcName AppStderr "C:\guardia\logs\guardia-itsm-err.log"
|
||||||
|
|
||||||
New-Item -ItemType Directory -Force "C:\guardia\logs" | Out-Null
|
|
||||||
nssm start $svcName
|
nssm start $svcName
|
||||||
Write-OK "Windows 서비스 등록 완료"
|
Write-OK "GUARDiA ITSM service registered"
|
||||||
|
|
||||||
# ── Nginx 리버스 프록시 ──────────────────────────────────────
|
# Nginx reverse proxy
|
||||||
$nginxConf = "C:\tools\nginx-winssl\conf\conf.d\guardia.conf"
|
$nginxBase = "C:\tools\nginx-winssl"
|
||||||
|
if (-not (Test-Path $nginxBase)) {
|
||||||
|
$nginxCmd = Get-Command nginx -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ($nginxCmd) { $nginxBase = Split-Path $nginxCmd.Source }
|
||||||
|
}
|
||||||
|
if ($nginxBase) {
|
||||||
|
$nginxConf = "$nginxBase\conf\conf.d\guardia.conf"
|
||||||
New-Item -ItemType Directory -Force (Split-Path $nginxConf) | Out-Null
|
New-Item -ItemType Directory -Force (Split-Path $nginxConf) | Out-Null
|
||||||
@"
|
$ngxLines = @(
|
||||||
server {
|
"server {",
|
||||||
listen 80;
|
" listen 80;",
|
||||||
server_name _;
|
" server_name _;",
|
||||||
client_max_body_size 100M;
|
" client_max_body_size 100M;",
|
||||||
|
" location / {",
|
||||||
location / {
|
" proxy_pass http://127.0.0.1:8001;",
|
||||||
proxy_pass http://127.0.0.1:8001;
|
" proxy_http_version 1.1;",
|
||||||
proxy_http_version 1.1;
|
' proxy_set_header Upgrade $http_upgrade;',
|
||||||
proxy_set_header Upgrade `$http_upgrade;
|
' proxy_set_header Connection "upgrade";',
|
||||||
proxy_set_header Connection "upgrade";
|
' proxy_set_header Host $host;',
|
||||||
proxy_set_header Host `$host;
|
' proxy_set_header X-Real-IP $remote_addr;',
|
||||||
proxy_set_header X-Real-IP `$remote_addr;
|
" proxy_read_timeout 300s;",
|
||||||
proxy_read_timeout 300s;
|
" }",
|
||||||
|
"}"
|
||||||
|
)
|
||||||
|
Set-Content $nginxConf -Value ($ngxLines -join "`r`n") -Encoding UTF8
|
||||||
|
Write-OK "Nginx configured"
|
||||||
}
|
}
|
||||||
}
|
|
||||||
"@ | Out-File -FilePath $nginxConf -Encoding utf8
|
|
||||||
|
|
||||||
# ── Ollama (온프레미스 sLLM) ──────────────────────────────────
|
# ==============================================================
|
||||||
|
# [10/10] Ollama + Firewall
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "[9/10] Ollama (온프레미스 sLLM 서버) 설치..."
|
Write-Host "[10/10] Ollama + Firewall..."
|
||||||
|
|
||||||
$OllamaInstall = if ($env:OLLAMA_INSTALL) { $env:OLLAMA_INSTALL } else { "online" }
|
$OllamaInstall = if ($env:OLLAMA_INSTALL) { $env:OLLAMA_INSTALL } else { "online" }
|
||||||
$OllamaModels = if ($env:OLLAMA_MODELS) { $env:OLLAMA_MODELS } else { "llama3.1:8b" }
|
$OllamaModels = if ($env:OLLAMA_MODELS) { $env:OLLAMA_MODELS } else { "llama3.1:8b" }
|
||||||
|
|
||||||
if ($OllamaInstall -eq "skip") {
|
if ($OllamaInstall -eq "skip") {
|
||||||
Write-Warn "Ollama 설치 건너뜀 (OLLAMA_INSTALL=skip) — 수동 설치 필요"
|
Write-Warn "Ollama skipped (OLLAMA_INSTALL=skip)"
|
||||||
} else {
|
} elseif ($OllamaInstall -eq "offline") {
|
||||||
$ollamaExe = "$env:LocalAppData\Programs\Ollama\ollama.exe"
|
$binPath = if ($env:OLLAMA_BIN_PATH) { $env:OLLAMA_BIN_PATH } else { "$env:TEMP\OllamaSetup.exe" }
|
||||||
if ($OllamaInstall -eq "offline") {
|
|
||||||
$binPath = if ($env:OLLAMA_BIN_PATH) { $env:OLLAMA_BIN_PATH } else { "$env:TEMP\ollama-setup.exe" }
|
|
||||||
if (Test-Path $binPath) {
|
if (Test-Path $binPath) {
|
||||||
& $binPath /S 2>$null
|
& $binPath /S 2>$null
|
||||||
} else { Write-Warn "오프라인: OLLAMA_BIN_PATH에 설치파일 필요" }
|
Write-OK "Ollama offline install complete"
|
||||||
|
} else {
|
||||||
|
Write-Warn "Offline: set OLLAMA_BIN_PATH to installer file"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
choco install ollama -y --no-progress 2>&1 | Out-Null
|
choco install ollama -y --no-progress 2>&1 | Out-Null
|
||||||
if (-not (Get-Command ollama -ErrorAction SilentlyContinue)) {
|
$mp3 = [System.Environment]::GetEnvironmentVariable("Path", "Machine")
|
||||||
# Chocolatey 실패 시 공식 설치파일 다운로드
|
$up3 = [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||||
$ollamaSetup = "$env:TEMP\OllamaSetup.exe"
|
$env:Path = $mp3 + ";" + $up3
|
||||||
Invoke-WebRequest "https://ollama.com/download/OllamaSetup.exe" `
|
|
||||||
-OutFile $ollamaSetup -UseBasicParsing -TimeoutSec 120
|
|
||||||
& $ollamaSetup /S
|
|
||||||
Start-Sleep -Seconds 5
|
|
||||||
}
|
|
||||||
Write-OK "Ollama 설치 완료"
|
|
||||||
} catch {
|
|
||||||
Write-Warn "Ollama 설치 실패: $_ — 수동 설치: https://ollama.com/download"
|
|
||||||
$OllamaInstall = "failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($OllamaInstall -ne "failed") {
|
|
||||||
# NSSM 서비스로 등록 (또는 기본 설치된 서비스 사용)
|
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" +
|
|
||||||
[System.Environment]::GetEnvironmentVariable("Path","User")
|
|
||||||
Start-Sleep -Seconds 3
|
Start-Sleep -Seconds 3
|
||||||
|
if (Get-Command ollama -ErrorAction SilentlyContinue) {
|
||||||
# 모델 다운로드 (온라인 환경)
|
|
||||||
if ($OllamaInstall -eq "online" -and (Get-Command ollama -ErrorAction SilentlyContinue)) {
|
|
||||||
foreach ($model in $OllamaModels.Split(" ")) {
|
foreach ($model in $OllamaModels.Split(" ")) {
|
||||||
Write-Host " 모델 다운로드: $model (시간이 걸릴 수 있습니다...)"
|
Write-Host " Pulling model: $model"
|
||||||
ollama pull $model 2>&1 | Select-Object -Last 3 | ForEach-Object { Write-Host " $_" }
|
ollama pull $model 2>&1 | Select-Object -Last 3 | ForEach-Object { Write-Host " $_" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-OK "Ollama 준비 완료 (http://localhost:11434)"
|
Write-OK "Ollama ready (http://localhost:11434)"
|
||||||
|
} catch {
|
||||||
|
Write-Warn "Ollama install failed: $_ - manual: https://ollama.com/download"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── 방화벽 규칙 ──────────────────────────────────────────────
|
# Firewall rules
|
||||||
New-NetFirewallRule -DisplayName "GUARDiA HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow 2>$null
|
try {
|
||||||
New-NetFirewallRule -DisplayName "GUARDiA HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow 2>$null
|
New-NetFirewallRule -DisplayName "GUARDiA HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow -ErrorAction SilentlyContinue | Out-Null
|
||||||
# Ollama/Tomcat은 내부 전용 — 외부 노출 차단
|
New-NetFirewallRule -DisplayName "GUARDiA HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow -ErrorAction SilentlyContinue | Out-Null
|
||||||
New-NetFirewallRule -DisplayName "Block Ollama External" -Direction Inbound -Protocol TCP -LocalPort 11434 -Action Block -RemoteAddress 0.0.0.0/0 2>$null
|
New-NetFirewallRule -DisplayName "Block Ollama" -Direction Inbound -Protocol TCP -LocalPort 11434 -Action Block -ErrorAction SilentlyContinue | Out-Null
|
||||||
New-NetFirewallRule -DisplayName "Block Tomcat External" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Block -RemoteAddress 0.0.0.0/0 2>$null
|
New-NetFirewallRule -DisplayName "Block Tomcat" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Block -ErrorAction SilentlyContinue | Out-Null
|
||||||
Write-OK "방화벽 규칙 추가 완료 (80/443 허용, 8080/11434 내부 전용)"
|
Write-OK "Firewall rules applied"
|
||||||
|
} catch {
|
||||||
|
Write-Warn "Firewall setup failed: $_"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================
|
||||||
|
# Summary
|
||||||
|
# ==============================================================
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "=================================================="
|
Write-Host "=================================================="
|
||||||
Write-OK "GUARDiA ITSM 설치 완료 — Windows Server [10/10]"
|
Write-OK "GUARDiA ITSM Setup Complete - Windows Server [10/10]"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
$serverIp = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object { $_.InterfaceAlias -notlike "*Loopback*" } | Select-Object -First 1).IPAddress
|
|
||||||
|
$serverIp = ""
|
||||||
|
$ipAddrs = Get-NetIPAddress -AddressFamily IPv4 -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.InterfaceAlias -notlike "*Loopback*" -and $_.PrefixOrigin -ne "WellKnown" } |
|
||||||
|
Select-Object -First 1
|
||||||
|
if ($ipAddrs) { $serverIp = $ipAddrs.IPAddress }
|
||||||
|
|
||||||
Write-Info "GUARDiA URL: http://$serverIp"
|
Write-Info "GUARDiA URL: http://$serverIp"
|
||||||
Write-Info "Tomcat URL: http://${serverIp}:8080 (내부 전용)"
|
Write-Info "Tomcat URL: http://${serverIp}:8080 (internal only)"
|
||||||
Write-Info "Ollama URL: http://localhost:11434 (내부 전용)"
|
Write-Info "Ollama URL: http://localhost:11434 (internal only)"
|
||||||
Write-Info "설치 로그: $LogFile"
|
Write-Info "Log: $LogFile"
|
||||||
Write-Info "검증: .\setup_windows.ps1 -Test"
|
Write-Info "Verify: .\setup_windows.ps1 -Test"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Warn "보안 필수 조치:"
|
Write-Warn "Security actions required:"
|
||||||
Write-Warn " 1. $envFile 의 SECRET_KEY 변경"
|
Write-Warn " 1. Change SECRET_KEY in $envFile"
|
||||||
Write-Warn " 2. PostgreSQL postgres 계정 비밀번호 변경"
|
Write-Warn " 2. Change PostgreSQL postgres password"
|
||||||
Write-Warn " 3. Tomcat opsagent 비밀번호 변경"
|
Write-Warn " 3. Change Tomcat opsagent password"
|
||||||
Write-Host "=================================================="
|
Write-Host "=================================================="
|
||||||
|
|
||||||
Stop-Transcript | Out-Null
|
Stop-Transcript | Out-Null
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user