#!/bin/bash # ============================================================================= # Document Server - Synology DS1525+ 최적화 배포 스크립트 # # 하드웨어 사양: # - CPU: AMD Ryzen R1600 (4코어/8스레드) # - RAM: 32GB DDR4 ECC # - SSD: 읽기/쓰기 캐시 활성화 # - Storage: Volume1(SSD), Volume2(HDD) # ============================================================================= set -e # 에러 발생 시 스크립트 중단 # 색상 정의 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 로그 함수 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 환경 변수 설정 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" COMPOSE_FILE="docker-compose.synology-optimized.yml" # 기본 환경 변수 export DB_PASSWORD="${DB_PASSWORD:-$(openssl rand -base64 32)}" export SECRET_KEY="${SECRET_KEY:-$(openssl rand -base64 64)}" export ADMIN_EMAIL="${ADMIN_EMAIL:-admin@document-server.local}" export ADMIN_PASSWORD="${ADMIN_PASSWORD:-$(openssl rand -base64 16)}" export DOMAIN_NAME="${DOMAIN_NAME:-localhost}" log_info "🚀 Synology DS1525+ 최적화 배포 시작" log_info "📁 프로젝트 디렉토리: $PROJECT_DIR" # 1. 시스템 요구사항 확인 log_info "🔍 시스템 요구사항 확인 중..." # Docker 및 Docker Compose 확인 if ! command -v docker &> /dev/null; then log_error "Docker가 설치되지 않았습니다." exit 1 fi if ! command -v docker-compose &> /dev/null; then log_error "Docker Compose가 설치되지 않았습니다." exit 1 fi # 메모리 확인 (최소 16GB 권장) TOTAL_MEM=$(free -g | awk '/^Mem:/{print $2}') if [ "$TOTAL_MEM" -lt 16 ]; then log_warning "메모리가 ${TOTAL_MEM}GB입니다. 최소 16GB를 권장합니다." fi log_success "시스템 요구사항 확인 완료" # 2. 디렉토리 구조 생성 log_info "📂 디렉토리 구조 생성 중..." # SSD 디렉토리 (성능 최우선) SSD_DIRS=( "/volume1/docker/document-server/database" "/volume1/docker/document-server/redis" "/volume1/docker/document-server/logs" "/volume1/docker/document-server/logs/nginx" "/volume1/docker/document-server/config" "/volume1/docker/document-server/nginx/conf.d" "/volume1/docker/document-server/nginx/cache" "/volume1/docker/document-server/cache" ) # HDD 디렉토리 (대용량 저장) HDD_DIRS=( "/volume2/document-storage/uploads" "/volume2/document-storage/documents" "/volume2/document-storage/thumbnails" "/volume2/document-storage/backups" "/volume2/document-storage/archives" ) # SSD 디렉토리 생성 for dir in "${SSD_DIRS[@]}"; do if [ ! -d "$dir" ]; then sudo mkdir -p "$dir" log_info "SSD 디렉토리 생성: $dir" fi done # HDD 디렉토리 생성 for dir in "${HDD_DIRS[@]}"; do if [ ! -d "$dir" ]; then sudo mkdir -p "$dir" log_info "HDD 디렉토리 생성: $dir" fi done # 권한 설정 sudo chown -R 1000:1000 /volume1/docker/document-server/ sudo chown -R 1000:1000 /volume2/document-storage/ log_success "디렉토리 구조 생성 완료" # 3. 설정 파일 복사 log_info "⚙️ 설정 파일 생성 중..." # PostgreSQL 설정 (32GB RAM 최적화) cat > /volume1/docker/document-server/config/postgresql.synology.conf << 'EOF' # PostgreSQL 설정 - Synology DS1525+ 32GB RAM 최적화 # 메모리 설정 (32GB RAM 기준) shared_buffers = 8GB # RAM의 25% effective_cache_size = 24GB # RAM의 75% work_mem = 512MB # 복잡한 쿼리용 (증가) maintenance_work_mem = 4GB # 인덱스 구축용 (증가) # 체크포인트 설정 (SSD 최적화) checkpoint_completion_target = 0.9 wal_buffers = 128MB # WAL 버퍼 (증가) checkpoint_timeout = 15min max_wal_size = 4GB min_wal_size = 1GB # SSD 최적화 random_page_cost = 1.1 # SSD 환경 effective_io_concurrency = 200 # SSD 동시 I/O seq_page_cost = 1.0 # 병렬 처리 (4코어/8스레드 최적화) max_worker_processes = 8 max_parallel_workers_per_gather = 4 max_parallel_workers = 8 max_parallel_maintenance_workers = 4 # 연결 설정 max_connections = 200 shared_preload_libraries = 'pg_stat_statements' # 로깅 설정 log_min_duration_statement = 1000 # 1초 이상 쿼리 로깅 log_checkpoints = on log_connections = on log_disconnections = on log_lock_waits = on # 자동 VACUUM 설정 autovacuum = on autovacuum_max_workers = 4 autovacuum_naptime = 30s EOF # Nginx 설정 (SSD 캐시 최적화) cat > /volume1/docker/document-server/nginx/conf.d/default.conf << 'EOF' # Nginx 설정 - SSD 캐시 최적화 # 업스트림 백엔드 upstream backend { server backend:8000; keepalive 32; } # 캐시 존 정의 (SSD에 저장) proxy_cache_path /var/cache/nginx/documents levels=1:2 keys_zone=documents:100m max_size=2g inactive=60m use_temp_path=off; proxy_cache_path /var/cache/nginx/api levels=1:2 keys_zone=api:50m max_size=500m inactive=10m use_temp_path=off; server { listen 80; server_name _; # 클라이언트 설정 client_max_body_size 500M; client_body_timeout 300s; client_header_timeout 300s; # Gzip 압축 gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; # 정적 파일 (SSD에서 서빙) location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; # 정적 파일 캐시 location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } } # 업로드된 문서 (HDD에서 서빙, SSD 캐시) location /uploads/ { alias /usr/share/nginx/html/uploads/; # 문서 캐시 (자주 접근하는 문서는 SSD에 캐시) proxy_cache documents; proxy_cache_valid 200 60m; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; add_header X-Cache-Status $upstream_cache_status; expires 1h; } # API 요청 location /api/ { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # API 응답 캐시 (GET 요청만) proxy_cache api; proxy_cache_methods GET HEAD; proxy_cache_valid 200 5m; proxy_cache_bypass $http_pragma $http_authorization; add_header X-Cache-Status $upstream_cache_status; # 타임아웃 설정 proxy_connect_timeout 30s; proxy_send_timeout 300s; proxy_read_timeout 300s; } # 헬스체크 location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } } EOF log_success "설정 파일 생성 완료" # 4. 환경 변수 파일 생성 log_info "🔐 환경 변수 설정 중..." cat > "$PROJECT_DIR/.env.synology" << EOF # Synology DS1525+ 배포 환경 변수 DB_PASSWORD=$DB_PASSWORD SECRET_KEY=$SECRET_KEY ADMIN_EMAIL=$ADMIN_EMAIL ADMIN_PASSWORD=$ADMIN_PASSWORD DOMAIN_NAME=$DOMAIN_NAME # 성능 최적화 설정 POSTGRES_SHARED_BUFFERS=8GB POSTGRES_EFFECTIVE_CACHE_SIZE=24GB REDIS_MAXMEMORY=8gb # 경로 설정 SSD_PATH=/volume1/docker/document-server HDD_PATH=/volume2/document-storage EOF log_success "환경 변수 설정 완료" # 5. Docker Compose 배포 log_info "🐳 Docker 컨테이너 배포 중..." cd "$PROJECT_DIR" # 기존 컨테이너 중지 및 제거 (있는 경우) if docker-compose -f "$COMPOSE_FILE" ps -q | grep -q .; then log_warning "기존 컨테이너를 중지합니다..." docker-compose -f "$COMPOSE_FILE" down fi # 이미지 빌드 및 컨테이너 시작 log_info "이미지 빌드 중..." docker-compose -f "$COMPOSE_FILE" build --no-cache log_info "컨테이너 시작 중..." docker-compose -f "$COMPOSE_FILE" up -d # 6. 서비스 상태 확인 log_info "🔍 서비스 상태 확인 중..." # 컨테이너 시작 대기 sleep 30 # 헬스체크 services=("database" "redis" "backend" "nginx") for service in "${services[@]}"; do if docker-compose -f "$COMPOSE_FILE" ps "$service" | grep -q "Up"; then log_success "$service 서비스 정상 실행 중" else log_error "$service 서비스 실행 실패" docker-compose -f "$COMPOSE_FILE" logs "$service" fi done # 7. 백업 스크립트 설정 log_info "💾 백업 스크립트 설정 중..." cat > /volume1/docker/document-server/backup.sh << 'EOF' #!/bin/bash # 자동 백업 스크립트 BACKUP_DIR="/volume2/document-storage/backups" DATE=$(date +%Y%m%d_%H%M%S) # 데이터베이스 백업 docker exec document-server-db pg_dump -U docuser document_db > "$BACKUP_DIR/db_backup_$DATE.sql" # 설정 파일 백업 tar -czf "$BACKUP_DIR/config_backup_$DATE.tar.gz" /volume1/docker/document-server/config/ # 7일 이상 된 백업 파일 삭제 find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete echo "백업 완료: $DATE" EOF chmod +x /volume1/docker/document-server/backup.sh log_success "백업 스크립트 설정 완료" # 8. 배포 완료 정보 출력 log_success "🎉 Synology DS1525+ 배포 완료!" echo "" echo "=== 배포 정보 ===" echo "🌐 웹 인터페이스: http://localhost:24100" echo "🔧 API 서버: http://localhost:24102" echo "🗄️ 데이터베이스: localhost:24101" echo "💾 Redis: localhost:24103" echo "" echo "=== 관리자 계정 ===" echo "📧 이메일: $ADMIN_EMAIL" echo "🔑 비밀번호: $ADMIN_PASSWORD" echo "" echo "=== 스토리지 구성 ===" echo "💿 SSD (성능): /volume1/docker/document-server/" echo "💾 HDD (용량): /volume2/document-storage/" echo "" echo "=== 자동 백업 ===" echo "📅 매일 새벽 2시 자동 백업 (Synology 작업 스케줄러에서 설정)" echo "📂 백업 위치: /volume2/document-storage/backups/" echo "" echo "=== 모니터링 명령어 ===" echo "docker-compose -f $COMPOSE_FILE ps" echo "docker-compose -f $COMPOSE_FILE logs -f" echo "docker stats" log_info "배포 스크립트 실행 완료"