#!/bin/bash # ============================================ # FLNXI素材库 - 全自动安装脚本 # 自动安装 Docker、Docker Compose 和应用 # ============================================ set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' echo "========================================" echo " FLNXI素材库 - 全自动安装" echo "========================================" echo "" echo "此脚本将自动安装:" echo " ✓ Docker" echo " ✓ Docker Compose" echo " ✓ FLNXI素材库系统" echo "" # 检查是否为root用户 if [ "$EUID" -ne 0 ]; then echo -e "${YELLOW}提示: 建议使用 root 用户或 sudo 运行此脚本${NC}" echo "如果遇到权限问题,请使用: sudo bash $0" echo "" fi # 检测操作系统 detect_os() { if [ -f /etc/os-release ]; then . /etc/os-release OS=$ID OS_VERSION=$VERSION_ID elif [ -f /etc/redhat-release ]; then OS="centos" else OS=$(uname -s) fi echo -e "${BLUE}检测到操作系统: $OS $OS_VERSION${NC}" } # 安装 Docker install_docker() { echo "" echo -e "${BLUE}[1/4]${NC} 检查 Docker..." if command -v docker &> /dev/null; then DOCKER_VERSION=$(docker --version | awk '{print $3}' | sed 's/,//') echo -e "${GREEN}✓ Docker 已安装 (版本: $DOCKER_VERSION)${NC}" # 检查 Docker 是否运行 if ! docker ps &> /dev/null; then echo -e "${YELLOW}Docker 未运行,尝试启动...${NC}" if command -v systemctl &> /dev/null; then sudo systemctl start docker sudo systemctl enable docker else sudo service docker start fi sleep 3 fi return 0 fi echo -e "${YELLOW}未检测到 Docker,开始安装...${NC}" case $OS in ubuntu|debian) echo "使用 APT 安装 Docker..." sudo apt-get update sudo apt-get install -y \ ca-certificates \ curl \ gnupg \ lsb-release # 添加 Docker 官方 GPG key sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/$OS/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加 Docker 仓库 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$OS \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装 Docker sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ;; centos|rhel|fedora) echo "使用 YUM/DNF 安装 Docker..." sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin ;; *) echo -e "${YELLOW}使用通用安装脚本...${NC}" curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh rm get-docker.sh ;; esac # 启动 Docker if command -v systemctl &> /dev/null; then sudo systemctl start docker sudo systemctl enable docker else sudo service docker start fi # 将当前用户添加到 docker 组 if [ "$EUID" -ne 0 ]; then sudo usermod -aG docker $USER echo -e "${YELLOW}注意: 需要重新登录以使 docker 组权限生效${NC}" echo -e "${YELLOW}或运行: newgrp docker${NC}" fi sleep 3 echo -e "${GREEN}✓ Docker 安装完成${NC}" } # 安装 Docker Compose install_docker_compose() { echo "" echo -e "${BLUE}[2/4]${NC} 检查 Docker Compose..." # 检查是否已有 docker compose 插件 if docker compose version &> /dev/null; then COMPOSE_VERSION=$(docker compose version | awk '{print $4}') echo -e "${GREEN}✓ Docker Compose 已安装 (版本: $COMPOSE_VERSION)${NC}" DOCKER_COMPOSE="docker compose" return 0 fi # 检查旧版 docker-compose if command -v docker-compose &> /dev/null; then COMPOSE_VERSION=$(docker-compose --version | awk '{print $4}' | sed 's/,//') echo -e "${GREEN}✓ Docker Compose 已安装 (版本: $COMPOSE_VERSION)${NC}" DOCKER_COMPOSE="docker-compose" return 0 fi echo -e "${YELLOW}未检测到 Docker Compose,开始安装...${NC}" # 安装 Docker Compose 插件(推荐方式) case $OS in ubuntu|debian) # 应该已随 Docker 安装 if ! docker compose version &> /dev/null; then sudo apt-get update sudo apt-get install -y docker-compose-plugin fi ;; centos|rhel|fedora) # 应该已随 Docker 安装 if ! docker compose version &> /dev/null; then sudo yum install -y docker-compose-plugin fi ;; *) # 下载独立的 docker-compose COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4) sudo curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose ;; esac # 再次检查 if docker compose version &> /dev/null; then DOCKER_COMPOSE="docker compose" echo -e "${GREEN}✓ Docker Compose 安装完成${NC}" elif command -v docker-compose &> /dev/null; then DOCKER_COMPOSE="docker-compose" echo -e "${GREEN}✓ Docker Compose 安装完成${NC}" else echo -e "${RED}✗ Docker Compose 安装失败${NC}" exit 1 fi } # 配置环境 configure_environment() { echo "" echo -e "${BLUE}[3/4]${NC} 配置环境..." # 创建 .env 文件(如果不存在) if [ ! -f .env ]; then echo "正在自动检测服务器IP地址..." # 尝试多种方法获取IP SERVER_IP="" # 方法1: 通过 ip route 获取 if command -v ip &> /dev/null; then SERVER_IP=$(ip route get 1 2>/dev/null | awk '{print $7; exit}') fi # 方法2: 通过 hostname 获取 if [ -z "$SERVER_IP" ] && command -v hostname &> /dev/null; then SERVER_IP=$(hostname -I 2>/dev/null | awk '{print $1}') fi # 方法3: 通过 ifconfig 获取 if [ -z "$SERVER_IP" ] && command -v ifconfig &> /dev/null; then SERVER_IP=$(ifconfig 2>/dev/null | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | head -n 1 | sed 's/addr://') fi # 如果自动检测失败,使用默认值 if [ -z "$SERVER_IP" ]; then SERVER_IP="localhost" fi echo -e "${GREEN}检测到服务器IP: $SERVER_IP${NC}" # 询问是否修改 read -p "是否使用此IP? (Y/n): " -n 1 -r echo if [[ $REPLY =~ ^[Nn]$ ]]; then read -p "请输入服务器IP地址: " SERVER_IP fi # 生成随机密码 echo "生成安全密码..." POSTGRES_PASSWORD=$(openssl rand -base64 16 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) MINIO_ROOT_PASSWORD=$(openssl rand -base64 16 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) NEXTAUTH_SECRET=$(openssl rand -base64 32 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) # 询问初始管理员账号 echo "" echo "配置初始管理员账号 (首次登录使用):" read -p "管理员邮箱 [admin@flnxi.com]: " INIT_ADMIN_EMAIL INIT_ADMIN_EMAIL=${INIT_ADMIN_EMAIL:-admin@flnxi.com} read -sp "管理员密码 (输入时不会显示,留空将自动生成): " INIT_ADMIN_PASSWORD echo if [ -z "$INIT_ADMIN_PASSWORD" ]; then INIT_ADMIN_PASSWORD=$(openssl rand -base64 16 2>/dev/null || cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1) echo -e "${YELLOW}已自动生成密码${NC}" fi # 创建 .env.production 文件 cat > .env.production << EOF # FLNXI素材库 - 生产环境配置 # 生成时间: $(date) # 服务器配置 SERVER_IP=$SERVER_IP APP_PORT=4320 # 数据库配置 POSTGRES_USER=postgres POSTGRES_PASSWORD=$POSTGRES_PASSWORD POSTGRES_DB=flnxi # MinIO 配置 MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD MINIO_API_PORT=9000 MINIO_CONSOLE_PORT=9001 S3_BUCKET=flnxi-materials # 应用安全配置 NEXTAUTH_SECRET=$NEXTAUTH_SECRET NEXTAUTH_URL=http://$SERVER_IP:4320 APP_PUBLIC_URL=http://$SERVER_IP:4320 # 初始管理员账号 INIT_ADMIN_EMAIL=$INIT_ADMIN_EMAIL INIT_ADMIN_PASSWORD=$INIT_ADMIN_PASSWORD EOF echo -e "${GREEN}✓ 环境配置文件已创建${NC}" # 保存重要信息 cat > 系统信息.txt << EOF ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ FLNXI素材库 - 系统信息 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 安装时间: $(date) 服务器IP: $SERVER_IP 访问地址: 应用首页: http://$SERVER_IP:4320 MinIO控制台: http://$SERVER_IP:9001 MinIO 管理员账号: 用户名: minioadmin 密码: $MINIO_ROOT_PASSWORD 数据库信息: 数据库名: flnxi 用户名: postgres 密码: $POSTGRES_PASSWORD 初始管理员账号: 邮箱: $INIT_ADMIN_EMAIL 密码: $INIT_ADMIN_PASSWORD ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 重要提示:请妥善保管此文件! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ EOF echo "" echo -e "${YELLOW}重要信息已保存到: 系统信息.txt${NC}" echo -e "${YELLOW}请妥善保管此文件!${NC}" else echo -e "${GREEN}✓ 检测到已存在的配置文件${NC}" if [ -f .env.production ]; then source .env.production elif [ -f .env ]; then source .env fi fi # 创建必要的目录 mkdir -p uploads chmod 755 uploads echo -e "${GREEN}✓ 数据目录创建完成${NC}" } # 安装应用 install_application() { echo "" echo -e "${BLUE}[4/4]${NC} 安装应用..." # 停止旧容器(如果存在) echo "清理旧容器..." $DOCKER_COMPOSE down 2>/dev/null || true # 拉取镜像(从 Harbor) echo "拉取 Docker 镜像..." echo "这可能需要几分钟时间,请耐心等待..." $DOCKER_COMPOSE -f docker-compose.prod.yml pull # 启动服务 echo "启动服务..." $DOCKER_COMPOSE -f docker-compose.prod.yml up -d # 等待服务就绪 echo "等待服务启动..." sleep 15 # 初始化数据库 echo "初始化数据库..." max_retries=30 retry_count=0 while [ $retry_count -lt $max_retries ]; do if $DOCKER_COMPOSE -f docker-compose.prod.yml exec -T app npx prisma db push --accept-data-loss 2>/dev/null; then echo -e "${GREEN}✓ 数据库初始化成功${NC}" break else retry_count=$((retry_count + 1)) if [ $retry_count -lt $max_retries ]; then echo "等待应用启动... ($retry_count/$max_retries)" sleep 5 else echo -e "${RED}数据库初始化超时,请稍后手动执行:${NC}" echo " $DOCKER_COMPOSE -f docker-compose.prod.yml exec app npx prisma db push" fi fi done echo -e "${GREEN}✓ 应用安装完成${NC}" } # 显示安装结果 show_result() { source .env echo "" echo "========================================" echo -e "${GREEN} 安装完成!${NC}" echo "========================================" echo "" echo -e "${BLUE}访问地址:${NC}" echo " 应用首页: http://$SERVER_IP:${APP_PORT:-4320}" echo " MinIO控制台: http://$SERVER_IP:${MINIO_CONSOLE_PORT:-9001}" echo "" echo -e "${BLUE}MinIO 管理员账号:${NC}" echo " 用户名: minioadmin" echo " 密码: (查看 系统信息.txt)" echo "" echo -e "${BLUE}首次使用:${NC}" echo " 1. 访问 http://$SERVER_IP:${APP_PORT:-4320}" echo " 2. 使用初始管理员账号登录(查看 系统信息.txt)" echo " 3. 登录后可在系统设置中修改密码" echo "" echo -e "${BLUE}常用命令:${NC}" echo " 查看服务: $DOCKER_COMPOSE -f docker-compose.prod.yml ps" echo " 查看日志: $DOCKER_COMPOSE -f docker-compose.prod.yml logs -f" echo " 重启服务: $DOCKER_COMPOSE -f docker-compose.prod.yml restart" echo " 停止服务: $DOCKER_COMPOSE -f docker-compose.prod.yml down" echo "" echo -e "${YELLOW}重要: 系统信息已保存到 系统信息.txt${NC}" echo "========================================" } # 主流程 main() { detect_os install_docker install_docker_compose configure_environment install_application show_result } # 运行 main