#!/usr/bin/env bash set -Eeuo pipefail REPOSITORY_URL="${REPOSITORY_URL:-https://github.com/ddcat-ai/open-ai-canvas.git}" REPOSITORY_REF="${REPOSITORY_REF:-main}" INSTALL_DIR="${INSTALL_DIR:-/opt/open-ai-canvas}" CANVAS_HTTP_PORT="${CANVAS_HTTP_PORT:-3000}" COMPOSE_FILE="docker-compose.deploy.yml" BUILD_COMPOSE_FILE="docker-compose.build.yml" step() { printf '\n==> %s\n' "$1" } fail() { printf '\n安装失败:%s\n' "$1" >&2 exit 1 } require_root() { if [[ "${EUID}" -ne 0 ]]; then fail "请使用 README 中带 sudo 的一键安装命令" fi [[ "$(uname -s)" == "Linux" ]] || fail "一键部署脚本仅支持 Linux 服务器" [[ "$CANVAS_HTTP_PORT" =~ ^[0-9]+$ ]] || fail "CANVAS_HTTP_PORT 必须是 1 到 65535 的数字" ((CANVAS_HTTP_PORT >= 1 && CANVAS_HTTP_PORT <= 65535)) || fail "CANVAS_HTTP_PORT 必须是 1 到 65535 的数字" } install_packages() { local packages=(ca-certificates curl git openssl) if command -v apt-get >/dev/null 2>&1; then apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y "${packages[@]}" elif command -v dnf >/dev/null 2>&1; then dnf install -y "${packages[@]}" elif command -v yum >/dev/null 2>&1; then yum install -y "${packages[@]}" else fail "暂不支持当前 Linux 发行版,请先手动安装 Docker、Git、curl 和 OpenSSL" fi } install_docker() { if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then return fi step "安装 Docker 和 Docker Compose" local installer installer="$(mktemp)" curl -fsSL https://get.docker.com -o "$installer" sh "$installer" rm -f "$installer" if command -v systemctl >/dev/null 2>&1; then systemctl enable --now docker elif command -v service >/dev/null 2>&1; then service docker start fi docker compose version >/dev/null 2>&1 || fail "Docker Compose 安装失败" } sync_source() { step "下载影策源码" if [[ -d "$INSTALL_DIR/.git" ]]; then cd "$INSTALL_DIR" [[ -z "$(git status --porcelain --untracked-files=no)" ]] || fail "$INSTALL_DIR 存在本地代码改动,请先处理后再更新" git pull --ff-only origin "$REPOSITORY_REF" return fi if [[ -e "$INSTALL_DIR" && -n "$(find "$INSTALL_DIR" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)" ]]; then fail "$INSTALL_DIR 已存在且不是本脚本安装的仓库,为避免覆盖文件已停止" fi mkdir -p "$(dirname "$INSTALL_DIR")" git clone --depth 1 --branch "$REPOSITORY_REF" "$REPOSITORY_URL" "$INSTALL_DIR" cd "$INSTALL_DIR" } prepare_environment() { if [[ -f .env ]]; then grep -Eq '^POSTGRES_PASSWORD=.+$' .env || fail "现有 .env 缺少 POSTGRES_PASSWORD" grep -Eq '^DATABASE_URL=.+$' .env || fail "现有 .env 缺少 DATABASE_URL" local configured_http_port configured_http_port="$(sed -n 's/^CANVAS_HTTP_PORT=//p' .env | tail -n 1)" if [[ -n "$configured_http_port" ]]; then [[ "$configured_http_port" =~ ^[0-9]+$ ]] || fail ".env 中的 CANVAS_HTTP_PORT 无效" ((configured_http_port >= 1 && configured_http_port <= 65535)) || fail ".env 中的 CANVAS_HTTP_PORT 无效" CANVAS_HTTP_PORT="$configured_http_port" fi return fi step "生成 PostgreSQL 随机密码和部署配置" local database_password database_password="$(openssl rand -hex 32)" umask 077 cat >.env <