152 lines
5.3 KiB
Bash
Executable File
152 lines
5.3 KiB
Bash
Executable File
#!/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 <<EOF
|
||
POSTGRES_DB=open_ai_canvas
|
||
POSTGRES_USER=open_ai_canvas
|
||
POSTGRES_PASSWORD=${database_password}
|
||
DATABASE_URL=postgresql://open_ai_canvas:${database_password}@postgres:5432/open_ai_canvas?sslmode=disable
|
||
CANVAS_HTTP_PORT=${CANVAS_HTTP_PORT}
|
||
CANVAS_IMAGE_TAG=source
|
||
CANVAS_BACKEND_IMAGE=open-ai-canvas-backend:server
|
||
CANVAS_WEB_IMAGE=open-ai-canvas-web:server
|
||
CANVAS_YINGCE_AGENT_IMAGE=open-ai-canvas-yingce-agent:server
|
||
YINGCE_AGENT_TOKEN=$(openssl rand -hex 32)
|
||
CANVAS_REGISTRATION_ENABLED=false
|
||
CANVAS_ALLOW_PRIVATE_UPSTREAMS=false
|
||
CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS=
|
||
CANVAS_CORS_ORIGINS=
|
||
EOF
|
||
}
|
||
|
||
start_services() {
|
||
step "从源码构建网页、后端和 Agent 镜像"
|
||
# 标准一键部署已下载完整仓库,直接本地构建可避免公开项目被 GHCR 包可见性阻断。
|
||
docker compose --env-file .env -f "$COMPOSE_FILE" -f "$BUILD_COMPOSE_FILE" build migrate backend web yingce-agent
|
||
|
||
step "启动 PostgreSQL、Redis、后端和网页服务"
|
||
docker compose --env-file .env -f "$COMPOSE_FILE" -f "$BUILD_COMPOSE_FILE" up -d --remove-orphans --wait --wait-timeout 600
|
||
}
|
||
|
||
print_result() {
|
||
local local_ip
|
||
local_ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||
[[ -n "$local_ip" ]] || local_ip="服务器IP"
|
||
|
||
printf '\n部署完成。\n'
|
||
printf '访问地址:http://%s:%s\n' "$local_ip" "$CANVAS_HTTP_PORT"
|
||
printf '安装目录:%s\n' "$INSTALL_DIR"
|
||
printf '查看状态:cd %q && docker compose --env-file .env -f %s -f %s ps\n' "$INSTALL_DIR" "$COMPOSE_FILE" "$BUILD_COMPOSE_FILE"
|
||
printf '\n首次打开后注册的第一个账号会自动成为管理员。公网长期使用前请配置 HTTPS。\n'
|
||
}
|
||
|
||
main() {
|
||
require_root
|
||
step "安装服务器基础工具"
|
||
install_packages
|
||
install_docker
|
||
sync_source
|
||
prepare_environment
|
||
start_services
|
||
print_result
|
||
}
|
||
|
||
main "$@"
|