#!/usr/bin/env bash # 设置脚本在遇到错误时立即停止执行 set -e # 定义输出颜色,让终端显示更友好 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 重置颜色 # 脚本版本 VERSION="1.1.0-podman" # --- 日志辅助函数 --- 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"; } # --- 全局变量 --- SUFFIX="" ADMIN_TOKEN="" DB_PASSWORD="" DEPLOY_DIR="$HOME/claude-code-hub" # 针对 WSL2 的默认路径 IMAGE_TAG="latest" BRANCH_NAME="main" APP_PORT="23000" ENABLE_CADDY=false NON_INTERACTIVE=false # --- 检查 Podman 环境 --- check_podman() { log_info "正在检查 Podman 安装情况..." # 检查 podman 命令是否存在 if ! command -v podman &> /dev/null; then log_error "未检测到 Podman。请先在 Ubuntu 中运行: sudo apt update && sudo apt install -y podman podman-compose" exit 1 fi # 检查 podman-compose 是否存在 if ! command -v podman-compose &> /dev/null; then log_warning "未检测到 podman-compose,尝试通过 podman 直接解析 (需 Podman 3.0+)..." fi log_success "Podman 环境检查通过" podman --version } # --- 生成随机信息 --- generate_secrets() { SUFFIX=$(tr -dc 'a-z0-9' < /dev/urandom | head -c 4) # 生成 32 位随机 Token ADMIN_TOKEN=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32) # 生成数据库随机密码 DB_PASSWORD=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 24) log_info "已生成随机后缀、Token 和数据库密码" } # --- 创建目录结构 --- create_dirs() { log_info "创建部署目录: $DEPLOY_DIR" mkdir -p "$DEPLOY_DIR/data/postgres" mkdir -p "$DEPLOY_DIR/data/redis" } # --- 写入 Podman 配置文件 --- # 注意:Podman 对网络名称和容器名称的处理与 Docker 类似,但更强调非 root 运行 write_config_files() { log_info "正在生成 docker-compose.yaml 和 .env 文件..." # 生成 .env 文件 cat > "$DEPLOY_DIR/.env" << EOF ADMIN_TOKEN=${ADMIN_TOKEN} DB_USER=postgres DB_PASSWORD=${DB_PASSWORD} DB_NAME=claude_code_hub APP_PORT=${APP_PORT} AUTO_MIGRATE=true ENABLE_RATE_LIMIT=true SESSION_TTL=300 ENABLE_SECURE_COOKIES=false NODE_ENV=production TZ=Asia/Shanghai EOF chmod 600 "$DEPLOY_DIR/.env" # 生成 compose 文件 cat > "$DEPLOY_DIR/docker-compose.yaml" << EOF services: postgres: image: docker.io/library/postgres:15-alpine container_name: cch-db-${SUFFIX} restart: always environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=claude_code_hub volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s redis: image: docker.io/library/redis:7-alpine container_name: cch-redis-${SUFFIX} restart: always volumes: - ./data/redis:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s app: image: ghcr.io/ding113/claude-code-hub:${IMAGE_TAG} container_name: cch-app-${SUFFIX} depends_on: - postgres - redis env_file: - .env environment: - DSN=postgresql://postgres:${DB_PASSWORD}@postgres:5432/claude_code_hub - REDIS_URL=redis://redis:6379 - PORT=${APP_PORT} ports: - "${APP_PORT}:${APP_PORT}" restart: always EOF } # --- 启动服务 --- start_services() { log_info "正在启动 Podman 容器..." cd "$DEPLOY_DIR" # 优先使用 podman-compose,如果没有则尝试 podman compose if command -v podman-compose &> /dev/null; then podman-compose up -d else podman compose up -d fi log_success "部署完成!" } # --- 主函数 --- main() { log_info "开始在 WSL2/Podman 环境下进行一键部署 v${VERSION}" check_podman generate_secrets create_dirs write_config_files start_services echo "" log_success "==========================================" log_success " Claude Code Hub 部署成功 (Podman)" log_success " 访问地址: http://localhost:${APP_PORT}" log_success " 管理 Token: ${ADMIN_TOKEN}" log_success "==========================================" log_info "部署目录: $DEPLOY_DIR" } main "$@"