#!/bin/bash # ============================================================ # GUARDiA 폐쇄망 설치 패키지 다운로드 스크립트 # ============================================================ # 인터넷이 연결된 Linux 서버에서 실행하세요. # 모든 필요 파일을 setup/offline/ 에 다운로드합니다. # # 사용법: # bash setup/download_packages.sh [OS유형] # bash setup/download_packages.sh ubuntu # Ubuntu 20/22/24 # bash setup/download_packages.sh centos # CentOS 7/8/Stream # bash setup/download_packages.sh rhel # RHEL 8/9 # bash setup/download_packages.sh all # 세 OS 모두 # # 결과 디렉토리: # setup/offline/ # ├── ubuntu/ deb 패키지 + pip 휠 + 바이너리 # ├── centos/ rpm 패키지 + pip 휠 + 바이너리 # ├── rhel/ rpm 패키지 + pip 휠 + 바이너리 # ├── common/ 공통 바이너리 (Tomcat, Ollama, Chart.js 등) # └── python/ pip 휠 파일 (OS 공통) # ============================================================ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" GUARDIA_ROOT="$(dirname "$SCRIPT_DIR")" OFFLINE_DIR="$SCRIPT_DIR/offline" OS_TYPE="${1:-all}" TOMCAT_VER="${TOMCAT_VER:-9.0.98}" PYTHON_VER="${PYTHON_VER:-3.11}" 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 " $*"; } echo "==================================================" echo " GUARDiA 폐쇄망 패키지 다운로드" echo " 대상 OS: $OS_TYPE" echo " 저장 위치: $OFFLINE_DIR" echo "==================================================" mkdir -p "$OFFLINE_DIR/common" "$OFFLINE_DIR/python" # ── 공통 바이너리 다운로드 ────────────────────────────── download_common() { echo "" echo "=== 공통 바이너리 다운로드 ===" # Tomcat 9 TOMCAT_URL="https://archive.apache.org/dist/tomcat/tomcat-9/v${TOMCAT_VER}/bin/apache-tomcat-${TOMCAT_VER}.tar.gz" if [[ ! -f "$OFFLINE_DIR/common/apache-tomcat-${TOMCAT_VER}.tar.gz" ]]; then echo " Tomcat $TOMCAT_VER 다운로드..." wget -q "$TOMCAT_URL" -O "$OFFLINE_DIR/common/apache-tomcat-${TOMCAT_VER}.tar.gz" \ && ok "Tomcat $TOMCAT_VER" || warn "Tomcat 다운로드 실패" else info "Tomcat $TOMCAT_VER 이미 존재" fi # Ollama Linux AMD64 OLLAMA_VER="${OLLAMA_VER:-latest}" if [[ ! -f "$OFFLINE_DIR/common/ollama-linux-amd64" ]]; then echo " Ollama 바이너리 다운로드..." wget -q "https://ollama.com/download/ollama-linux-amd64" \ -O "$OFFLINE_DIR/common/ollama-linux-amd64" \ && chmod +x "$OFFLINE_DIR/common/ollama-linux-amd64" \ && ok "Ollama binary" \ || warn "Ollama 다운로드 실패" else info "Ollama 바이너리 이미 존재" fi # Chart.js (오프라인 대시보드용) if [[ ! -f "$OFFLINE_DIR/common/chart.umd.min.js" ]]; then echo " Chart.js 다운로드..." wget -q "https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js" \ -O "$OFFLINE_DIR/common/chart.umd.min.js" \ && ok "Chart.js 4.4.0" || warn "Chart.js 다운로드 실패" fi # NSSM (Windows 서비스 관리자) if [[ ! -f "$OFFLINE_DIR/common/nssm-2.24.zip" ]]; then echo " NSSM 다운로드..." wget -q "https://nssm.cc/release/nssm-2.24.zip" \ -O "$OFFLINE_DIR/common/nssm-2.24.zip" \ && ok "NSSM 2.24" || warn "NSSM 다운로드 실패" fi } # ── Python 패키지 (pip wheel) ─────────────────────────── download_python_packages() { echo "" echo "=== Python 패키지 다운로드 (pip wheel) ===" if [[ ! -d "$OFFLINE_DIR/python/wheels" ]]; then mkdir -p "$OFFLINE_DIR/python/wheels" echo " requirements.txt 기반 wheel 다운로드..." pip download \ -r "$GUARDIA_ROOT/itsm/requirements.txt" \ -d "$OFFLINE_DIR/python/wheels" \ --platform manylinux2014_x86_64 \ --python-version 311 \ --implementation cp \ --abi cp311 \ --only-binary=:all: \ 2>/dev/null || true # 일부 패키지는 소스 빌드 필요 — 아무 플랫폼 없이 재시도 pip download \ -r "$GUARDIA_ROOT/itsm/requirements.txt" \ -d "$OFFLINE_DIR/python/wheels" \ 2>/dev/null || true ok "Python 패키지 다운로드 완료 ($(ls "$OFFLINE_DIR/python/wheels" | wc -l)개)" else info "Python 패키지 이미 존재 ($(ls "$OFFLINE_DIR/python/wheels" | wc -l)개)" fi } # ── Ubuntu/Debian 패키지 ──────────────────────────────── download_ubuntu() { echo "" echo "=== Ubuntu .deb 패키지 다운로드 ===" if ! command -v apt-get &>/dev/null; then warn "apt-get 없음 — Ubuntu/Debian 환경에서 실행하거나 Docker로 다운로드하세요." warn " docker run --rm -v $OFFLINE_DIR/ubuntu:/downloads ubuntu:22.04 bash -c \\" warn " 'apt-get update && apt-get install -y --download-only -o Dir::Cache::Archives=/downloads [패키지목록]'" return fi UBUNTU_DIR="$OFFLINE_DIR/ubuntu" mkdir -p "$UBUNTU_DIR" apt-get update -qq PACKAGES=( python3.11 python3.11-venv python3.11-dev python3-pip openjdk-17-jdk openjdk-11-jdk openjdk-8-jdk-headless postgresql postgresql-contrib redis-server nginx fail2ban chrony curl wget git lsof unzip jq libpq-dev gcc ) echo " 패키지 다운로드 중 (${#PACKAGES[@]}개)..." apt-get install -y --download-only \ -o Dir::Cache::Archives="$UBUNTU_DIR" \ "${PACKAGES[@]}" 2>/dev/null \ && ok "Ubuntu .deb 다운로드 완료 ($(ls "$UBUNTU_DIR"/*.deb 2>/dev/null | wc -l)개)" \ || warn "일부 패키지 다운로드 실패 — 이미 설치된 패키지는 아래로 수동 복사:" # 이미 설치된 패키지의 캐시 복사 find /var/cache/apt/archives -name "*.deb" 2>/dev/null | while read -r f; do cp -n "$f" "$UBUNTU_DIR/" 2>/dev/null || true done # 오프라인 설치 스크립트 생성 cat > "$UBUNTU_DIR/install_offline.sh" << 'UBSCRIPT' #!/bin/bash # Ubuntu 오프라인 패키지 설치 set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo "Ubuntu 패키지 오프라인 설치 중..." dpkg -i "$SCRIPT_DIR"/*.deb 2>/dev/null || true apt-get install -f -y 2>/dev/null || true echo "완료" UBSCRIPT chmod +x "$UBUNTU_DIR/install_offline.sh" ok "Ubuntu 오프라인 설치 스크립트 생성" } # ── CentOS/RHEL rpm 패키지 ────────────────────────────── download_centos() { echo "" echo "=== CentOS/RHEL .rpm 패키지 다운로드 ===" if ! command -v dnf &>/dev/null && ! command -v yum &>/dev/null; then warn "dnf/yum 없음 — CentOS/RHEL 환경에서 실행하거나 Docker로 다운로드하세요." warn " docker run --rm -v $OFFLINE_DIR/centos:/downloads centos:stream9 bash -c \\" warn " 'dnf download --downloaddir=/downloads --resolve [패키지목록]'" return fi CENTOS_DIR="$OFFLINE_DIR/centos" mkdir -p "$CENTOS_DIR" PACKAGES=( python3.11 python3.11-devel python3-pip java-17-openjdk java-17-openjdk-devel java-11-openjdk java-1.8.0-openjdk postgresql-server postgresql-contrib redis nginx fail2ban chrony curl wget git lsof unzip jq postgresql-devel gcc ) PKG_MGR="dnf" command -v dnf &>/dev/null || PKG_MGR="yum" echo " 패키지 다운로드 중..." $PKG_MGR install -y --downloadonly \ --downloaddir="$CENTOS_DIR" \ "${PACKAGES[@]}" 2>/dev/null \ && ok "CentOS/RHEL .rpm 다운로드 완료 ($(ls "$CENTOS_DIR"/*.rpm 2>/dev/null | wc -l)개)" \ || warn "일부 패키지 다운로드 실패" cat > "$CENTOS_DIR/install_offline.sh" << 'RPMSCRIPT' #!/bin/bash # CentOS/RHEL 오프라인 패키지 설치 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" echo "RPM 패키지 오프라인 설치 중..." dnf install -y "$SCRIPT_DIR"/*.rpm --disablerepo='*' 2>/dev/null || \ yum install -y "$SCRIPT_DIR"/*.rpm 2>/dev/null || \ rpm -ivh --nodeps "$SCRIPT_DIR"/*.rpm 2>/dev/null || true echo "완료" RPMSCRIPT chmod +x "$CENTOS_DIR/install_offline.sh" ok "CentOS/RHEL 오프라인 설치 스크립트 생성" } # ── Ollama 모델 다운로드 ───────────────────────────────── download_ollama_models() { echo "" echo "=== Ollama 모델 다운로드 ===" MODELS_DIR="$OFFLINE_DIR/common/ollama-models" mkdir -p "$MODELS_DIR" MODELS=( "llama3.1:8b" "codellama:7b" ) if command -v ollama &>/dev/null; then for model in "${MODELS[@]}"; do echo " 모델 다운로드: $model" ollama pull "$model" 2>&1 | tail -3 || warn "$model 다운로드 실패" done # 모델 파일 압축 OLLAMA_HOME="${OLLAMA_MODELS:-$HOME/.ollama}" if [[ -d "$OLLAMA_HOME/models" ]]; then echo " 모델 파일 압축 중..." tar -czf "$MODELS_DIR/models.tar.gz" \ -C "$OLLAMA_HOME" models manifests 2>/dev/null \ && ok "Ollama 모델 압축 완료 ($(du -sh "$MODELS_DIR/models.tar.gz" | cut -f1))" \ || warn "모델 압축 실패" fi else warn "Ollama 미설치 — 모델 다운로드 건너뜀" info "설치 후 수동 실행: OLLAMA_MODELS_PATH=$MODELS_DIR ollama pull llama3.1:8b" fi } # ── Docker 이미지 패키지 ───────────────────────────────── download_docker_images() { echo "" echo "=== Docker 이미지 패키지 ===" if command -v docker &>/dev/null; then bash "$SCRIPT_DIR/docker_package.sh" "$OFFLINE_DIR/docker" ok "Docker 이미지 패키지 완료" else warn "Docker 미설치 — docker_package.sh를 Docker가 설치된 서버에서 별도 실행하세요." fi } # ── 설치 인덱스 생성 ───────────────────────────────────── create_index() { echo "" echo "=== 설치 인덱스 생성 ===" cat > "$OFFLINE_DIR/README.md" << RDEOF # GUARDiA 폐쇄망 설치 패키지 생성 일시: $(date) ## 디렉토리 구조 \`\`\` offline/ ├── common/ # 공통 바이너리 │ ├── apache-tomcat-${TOMCAT_VER}.tar.gz │ ├── ollama-linux-amd64 │ ├── chart.umd.min.js │ └── ollama-models/models.tar.gz ├── ubuntu/ # Ubuntu .deb 패키지 │ └── install_offline.sh ├── centos/ # CentOS/RHEL .rpm 패키지 │ └── install_offline.sh ├── python/ │ └── wheels/ # pip wheel 파일 └── docker/ # Docker 이미지 tar (있는 경우) \`\`\` ## 폐쇄망 설치 절차 ### Ubuntu \`\`\`bash # 1. OS 패키지 bash offline/ubuntu/install_offline.sh # 2. Python 패키지 pip install --no-index --find-links=offline/python/wheels -r itsm/requirements.txt # 3. Tomcat TOMCAT_MIRROR=file://\$(pwd)/offline/common bash setup/setup_ubuntu.sh \`\`\` ### CentOS/RHEL \`\`\`bash bash offline/centos/install_offline.sh pip install --no-index --find-links=offline/python/wheels -r itsm/requirements.txt TOMCAT_MIRROR=file://\$(pwd)/offline/common bash setup/setup_centos.sh \`\`\` ### Docker (Docker 설치된 서버) \`\`\`bash bash offline/docker/guardia-docker-*/docker_load.sh --start \`\`\` RDEOF ok "설치 인덱스 생성: $OFFLINE_DIR/README.md" } # ── 메인 실행 ──────────────────────────────────────────── download_common download_python_packages case "$OS_TYPE" in ubuntu) download_ubuntu ;; centos|rhel) download_centos ;; all) download_ubuntu download_centos ;; docker) download_docker_images ;; *) warn "알 수 없는 OS 유형: $OS_TYPE. ubuntu|centos|rhel|all|docker 중 선택하세요." ;; esac download_ollama_models create_index echo "" echo "==================================================" ok "다운로드 완료!" echo "" info "저장 위치: $OFFLINE_DIR" info "전체 크기: $(du -sh "$OFFLINE_DIR" | cut -f1)" echo "" info "패키지 압축 (USB 복사용):" info " tar -czf guardia-offline-$(date +%Y%m%d).tar.gz -C setup offline/" echo "=================================================="