#!/bin/bash set -e # CloudSearch 一键部署 # curl -sS https://gitea.timxx.cn/admin/CloudSearch/raw/branch/master/source_clean/deploy.sh | bash # # 环境变量(可选): # CORS_ORIGIN - 域名 (默认自动检测公网IP) # ADMIN_PASSWORD - 管理员密码 (留空自动生成) # JWT_SECRET - JWT密钥 (留空自动生成) # DEPLOY_DIR - 部署目录 (默认 /opt/cloudsearch) REPO_URL="https://gitea.timxx.cn/admin/CloudSearch.git" DEPLOY_DIR="${DEPLOY_DIR:-/opt/cloudsearch}" info() { echo "[INFO] $*"; } warn() { echo "[WARN] $*"; } err() { echo "[ERROR] $*"; } command -v docker &>/dev/null || { err "Docker未安装"; exit 1; } # -- CORS_ORIGIN -- if [ -z "$CORS_ORIGIN" ]; then PUBLIC_IP=$(curl -s --connect-timeout 3 ifconfig.me 2>/dev/null || curl -s --connect-timeout 3 ip.sb 2>/dev/null || echo "") if [ -n "$PUBLIC_IP" ]; then CORS_ORIGIN="http://${PUBLIC_IP}:9527" else CORS_ORIGIN="http://localhost:9527" fi warn "CORS_ORIGIN=$CORS_ORIGIN (自动检测)" fi # -- 拉取仓库 -- info "拉取仓库..." if [ -d "$DEPLOY_DIR/.git" ]; then cd "$DEPLOY_DIR" && git pull --ff-only origin master 2>/dev/null || true else rm -rf "$DEPLOY_DIR" git clone --depth 1 "$REPO_URL" "$DEPLOY_DIR" fi cd "$DEPLOY_DIR/source_clean" # -- 切换镜像模式 -- if grep -q '^ build:' docker-compose.yml 2>/dev/null; then info "切换镜像模式..." sed -i 's/^ build:/ # build:/' docker-compose.yml sed -i 's/^ context:/ # context:/' docker-compose.yml sed -i 's/^ dockerfile:/ # dockerfile:/' docker-compose.yml sed -i 's|^ # image: gitea.timxx.cn/admin/cloudsearch:latest| image: gitea.timxx.cn/admin/cloudsearch:latest|' docker-compose.yml fi # -- 检测 Redis -- info "检测Redis..." EXISTING_REDIS=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -i redis | grep -v CloudSearch | head -1) if [ -n "$EXISTING_REDIS" ]; then REDIS_URL="redis://${EXISTING_REDIS}:6379" info "复用已有Redis: $EXISTING_REDIS" else REDIS_URL="redis://redis:6379" info "使用Compose自带Redis" fi # -- 生成密钥 -- JWT_SECRET="${JWT_SECRET:-$(openssl rand -hex 32)}" ADMIN_PASSWORD="${ADMIN_PASSWORD:-$(openssl rand -base64 12 | tr -d '=+/' | head -c 16)}" # -- 生成 .env -- cat > .env </dev/null || true info "停止旧服务..." docker compose down --remove-orphans 2>/dev/null || true info "启动服务..." docker compose up -d # -- 等待就绪 -- info "等待服务就绪..." for i in $(seq 1 20); do if curl -s -o /dev/null -w '%{http_code}' http://localhost:9527/health 2>/dev/null | grep -q '200'; then break fi sleep 2 done # -- 强制写入管理员密码 -- info "同步管理员密码..." sleep 3 docker exec -e ADMIN_PASSWORD="$ADMIN_PASSWORD" CloudSearch_App node -e ' var bcrypt = require("bcryptjs"); var Database = require("better-sqlite3"); var db = new Database("/data/database.sqlite"); var pw = process.env.ADMIN_PASSWORD || ""; var hash = bcrypt.hashSync(pw, 10); var existing = db.prepare("SELECT id FROM admins WHERE username = ?").get("admin"); if (existing) { db.prepare("UPDATE admins SET password_hash = ? WHERE username = ?").run(hash, "admin"); } else { db.prepare("INSERT INTO admins (username, password_hash) VALUES (?, ?)").run("admin", hash); } db.close(); ' 2>/dev/null && info "密码已同步" || warn "密码同步失败,请稍后重试" # -- 验证 -- if docker compose ps 2>/dev/null | grep -q 'Up'; then echo "" echo "==============================================" echo " CloudSearch 部署完成" echo "==============================================" docker compose ps echo "" echo " 管理后台: ${CORS_ORIGIN}/admin/login" echo " 用户名: admin" echo " 密码: ${ADMIN_PASSWORD}" else err "启动失败: docker compose logs" exit 1 fi