G-1: 메신저 Webhook Relay + _send_to_room 실제 httpx 호출 구현 G-2: POST /api/tasks/bulk SR 대량작업 엔드포인트 (최대 100건) G-3: 라이선스 만료 알림 스케줄러 (매일 09:00 KST) G-4: 체험판 upgrade_banner 필드 + license.py 배너 로직 G-5: core/auto_rca.py + incidents/problem auto-rca 엔드포인트 G-6: core/deploy_impact.py + vibe impact-analysis 엔드포인트 G-7: core/ticket_classifier.py + SR 생성 시 AI 분류 + ai-suggestion API G-8: VulnPatchRecord 모델 + vuln_scan 패치추적 4개 엔드포인트 G-9: core/jira_sync.py + gateway Jira/Confluence 연동 엔드포인트 G-10: core/push_notify.py + routers/push.py + PushSubscription 모델 G-11: approvals 다중승인 (위임/서명/기한초과/마감연장) G-12: alembic.ini + migrations/ + cicd/migrate_to_postgres.sh 하네스: guardia-orchestrator 확장기능 Phase 반영 봇명령어: /sr /status /license /bulk 슬래시 명령어 추가 설치스크립트: setup/ (Ubuntu, CentOS, RHEL, Windows) --test 옵션 포함 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
225 lines
8.1 KiB
Bash
225 lines
8.1 KiB
Bash
#!/bin/bash
|
|
# =============================================================
|
|
# GUARDiA ITSM 설치 스크립트 — RHEL 8 / RHEL 9
|
|
# =============================================================
|
|
# 전제조건: 순수 RHEL OS (최소 설치), 유효한 RH 서브스크립션
|
|
# 실행 방법: sudo bash setup_rhel.sh
|
|
# 설치 테스트: bash setup_rhel.sh --test
|
|
# =============================================================
|
|
|
|
set -euo pipefail
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
GUARDIA_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
LOG_FILE="/var/log/guardia_install.log"
|
|
TEST_MODE="${1:-}"
|
|
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
|
fail() { echo -e "${RED}[FAIL]${NC} $*"; exit 1; }
|
|
info() { echo -e " $*"; }
|
|
|
|
exec > >(tee -a "$LOG_FILE") 2>&1
|
|
|
|
echo "=================================================="
|
|
echo " GUARDiA ITSM 설치 — RHEL 8/9"
|
|
echo " 시작: $(date)"
|
|
echo "=================================================="
|
|
|
|
[[ $EUID -eq 0 ]] || fail "root 권한으로 실행하세요: sudo bash $0"
|
|
|
|
# ── 테스트 모드 ──────────────────────────────────────────────
|
|
if [[ "$TEST_MODE" == "--test" ]]; then
|
|
echo "=== 설치 검증 모드 ==="
|
|
PASS=0; FAIL=0
|
|
|
|
check() {
|
|
local desc="$1"; shift
|
|
if "$@" &>/dev/null; then
|
|
ok "$desc"; ((PASS++))
|
|
else
|
|
echo -e "${RED}[FAIL]${NC} $desc"; ((FAIL++))
|
|
fi
|
|
}
|
|
|
|
check "Python 3.11+" python3.11 --version
|
|
check "PostgreSQL" pg_isready -q
|
|
check "Redis" redis-cli ping
|
|
check "GUARDiA 포트" bash -c 'curl -sf http://localhost:8001/api/dashboard/overview -o /dev/null'
|
|
check "Nginx" nginx -t
|
|
check "systemd" systemctl is-active guardia-itsm
|
|
check "SELinux 정책" bash -c 'getsebool httpd_can_network_connect | grep -q on'
|
|
|
|
echo ""
|
|
echo "검증 결과: 성공 $PASS / 실패 $FAIL"
|
|
[[ $FAIL -eq 0 ]] && ok "모든 검사 통과" || fail "일부 실패 — 로그: $LOG_FILE"
|
|
exit 0
|
|
fi
|
|
|
|
# ── RHEL 버전 확인 ────────────────────────────────────────
|
|
RHEL_VER=$(rpm -E %{rhel})
|
|
echo "RHEL 버전: $RHEL_VER"
|
|
|
|
# ── 1. 저장소 활성화 ─────────────────────────────────────────
|
|
echo ""
|
|
echo "[1/9] RHEL 저장소 활성화..."
|
|
subscription-manager repos --enable=rhel-${RHEL_VER}-for-x86_64-appstream-rpms 2>/dev/null || \
|
|
warn "서브스크립션 저장소 활성화 실패 — EPEL로 대체 시도"
|
|
|
|
# EPEL (구독 없이도 사용 가능한 경우)
|
|
dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-${RHEL_VER}.noarch.rpm 2>/dev/null || true
|
|
ok "저장소 설정 완료"
|
|
|
|
# ── 2. 패키지 설치 ──────────────────────────────────────────
|
|
echo ""
|
|
echo "[2/9] 시스템 패키지 설치..."
|
|
dnf install -y \
|
|
curl wget git gcc make openssl-devel libffi-devel \
|
|
python3.11 python3.11-devel python3-pip \
|
|
postgresql-server postgresql-contrib \
|
|
redis \
|
|
nginx \
|
|
unzip jq
|
|
|
|
ok "시스템 패키지 설치 완료"
|
|
|
|
# ── 3. Python 가상환경 ──────────────────────────────────────
|
|
echo ""
|
|
echo "[3/9] Python 가상환경 설정..."
|
|
mkdir -p /opt/guardia
|
|
python3.11 -m venv /opt/guardia/venv
|
|
source /opt/guardia/venv/bin/activate
|
|
pip install --upgrade pip -q
|
|
pip install -r "$GUARDIA_ROOT/itsm/requirements.txt" -q
|
|
ok "Python 환경 준비 완료"
|
|
|
|
# ── 4. PostgreSQL 초기화 ────────────────────────────────────
|
|
echo ""
|
|
echo "[4/9] PostgreSQL 설정..."
|
|
postgresql-setup --initdb 2>/dev/null || true
|
|
systemctl start postgresql
|
|
systemctl enable postgresql
|
|
|
|
sudo -u postgres psql -tc "SELECT 1 FROM pg_user WHERE usename='guardia'" | grep -q 1 || \
|
|
sudo -u postgres psql -c "CREATE USER guardia WITH PASSWORD 'guardia_secure_pw';"
|
|
sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='guardia'" | grep -q 1 || \
|
|
sudo -u postgres psql -c "CREATE DATABASE guardia OWNER guardia;"
|
|
|
|
# RHEL: pg_hba.conf 수정 (md5 인증)
|
|
PG_HBA=$(find /var/lib/pgsql -name pg_hba.conf 2>/dev/null | head -1)
|
|
if [[ -n "$PG_HBA" ]]; then
|
|
sed -i 's/ident/md5/g; s/peer/md5/g' "$PG_HBA" 2>/dev/null || true
|
|
systemctl restart postgresql
|
|
fi
|
|
ok "PostgreSQL 설정 완료"
|
|
|
|
# ── 5. Redis ────────────────────────────────────────────────
|
|
echo ""
|
|
echo "[5/9] Redis 시작..."
|
|
systemctl start redis
|
|
systemctl enable redis
|
|
ok "Redis 완료"
|
|
|
|
# ── 6. 환경 파일 ────────────────────────────────────────────
|
|
echo ""
|
|
echo "[6/9] 환경 설정 파일..."
|
|
ENV_FILE="$GUARDIA_ROOT/itsm/.env"
|
|
if [[ ! -f "$ENV_FILE" ]]; then
|
|
cat > "$ENV_FILE" << 'ENVEOF'
|
|
DATABASE_URL=postgresql+asyncpg://guardia:guardia_secure_pw@localhost:5432/guardia
|
|
SECRET_KEY=change_this_secret_key_in_production_min_32chars
|
|
ALGORITHM=HS256
|
|
ACCESS_TOKEN_EXPIRE_MINUTES=480
|
|
REDIS_URL=redis://localhost:6379/0
|
|
OLLAMA_BASE_URL=http://localhost:11434
|
|
GUARDIA_LLM_MODEL=llama3.1:8b
|
|
MESSENGER_BASE_URL=http://localhost:8002
|
|
MESSENGER_OPS_ROOM=ops
|
|
ENVEOF
|
|
warn ".env 생성됨 — SECRET_KEY 필수 변경: $ENV_FILE"
|
|
fi
|
|
|
|
# ── 7. DB 초기화 ────────────────────────────────────────────
|
|
echo ""
|
|
echo "[7/9] DB 초기화..."
|
|
cd "$GUARDIA_ROOT/itsm"
|
|
source /opt/guardia/venv/bin/activate
|
|
python -c "
|
|
import asyncio, sys
|
|
sys.path.insert(0, '.')
|
|
from dotenv import load_dotenv; load_dotenv('.env')
|
|
from database import init_db
|
|
asyncio.run(init_db())
|
|
print('DB OK')
|
|
" && ok "DB 초기화 완료"
|
|
|
|
# ── 8. systemd ──────────────────────────────────────────────
|
|
echo ""
|
|
echo "[8/9] systemd 서비스..."
|
|
cat > /etc/systemd/system/guardia-itsm.service << SVCEOF
|
|
[Unit]
|
|
Description=GUARDiA ITSM Server
|
|
After=network.target postgresql.service redis.service
|
|
|
|
[Service]
|
|
Type=exec
|
|
User=nginx
|
|
WorkingDirectory=$GUARDIA_ROOT/itsm
|
|
Environment="PATH=/opt/guardia/venv/bin"
|
|
EnvironmentFile=$GUARDIA_ROOT/itsm/.env
|
|
ExecStart=/opt/guardia/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8001 --workers 4
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
SVCEOF
|
|
|
|
systemctl daemon-reload
|
|
systemctl enable guardia-itsm
|
|
systemctl start guardia-itsm
|
|
ok "systemd 서비스 완료"
|
|
|
|
# ── 9. Nginx + SELinux ──────────────────────────────────────
|
|
echo ""
|
|
echo "[9/9] Nginx + SELinux 설정..."
|
|
cat > /etc/nginx/conf.d/guardia.conf << 'NGXEOF'
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
client_max_body_size 100M;
|
|
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8001;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
}
|
|
NGXEOF
|
|
|
|
# SELinux: 네트워크 연결 허용
|
|
setsebool -P httpd_can_network_connect 1 || warn "SELinux 설정 실패 (수동 설정 필요)"
|
|
semanage port -a -t http_port_t -p tcp 8001 2>/dev/null || true
|
|
|
|
systemctl enable nginx
|
|
systemctl start nginx
|
|
|
|
# 방화벽
|
|
firewall-cmd --permanent --add-service=http 2>/dev/null || true
|
|
firewall-cmd --permanent --add-service=https 2>/dev/null || true
|
|
firewall-cmd --reload 2>/dev/null || true
|
|
ok "Nginx + SELinux 완료"
|
|
|
|
echo ""
|
|
echo "=================================================="
|
|
ok "GUARDiA ITSM 설치 완료 — RHEL ${RHEL_VER}"
|
|
echo ""
|
|
info "접속 URL: http://$(hostname -I | awk '{print $1}')"
|
|
info "설치 로그: $LOG_FILE"
|
|
info "검증: sudo bash $0 --test"
|
|
echo "=================================================="
|