From 0361d0167ec9a2622d0116740b498371251821f5 Mon Sep 17 00:00:00 2001 From: gaokao-deploy Date: Tue, 11 Aug 2026 17:47:44 +0800 Subject: [PATCH] one-line deploy script --- init.sh | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 init.sh diff --git a/init.sh b/init.sh new file mode 100644 index 0000000..b593b43 --- /dev/null +++ b/init.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# ============================================================ +# 高考质量分析系统 · 一条命令部署(群晖/Linux Docker) +# 安全设计: +# - 令牌【交互静默输入】(不落命令行/shell历史) +# - 部署完成【自动删除令牌】(Gitea API), 失败则提示手动删 +# - 建议管理员生成【短过期令牌】(如 1 天), 双保险 +# 用法(服务器执行): +# bash -c "$(curl -fsSL http://192.168.1.6:3000/bennyao/gaokao-sys/raw/branch/master/deploy/init.sh)" \ +# -- APP_DIR=/volume2/docker/gaokao-sys DATA_DIR=/volume2/docker/gaokao-sys-data +# ============================================================ +set -e + +GITEA_HOST="${GITEA_HOST:-192.168.1.6}" +GITEA_PORT="${GITEA_PORT:-3000}" +GITEA_OWNER="${GITEA_OWNER:-bennyao}" +GITEA_REPO="${GITEA_REPO:-gaokao-sys}" +TOKEN_NAME="${TOKEN_NAME:-gaokao-deploy}" +APP_DIR="${APP_DIR:-/opt/gaokao-sys}" +DATA_DIR="${DATA_DIR:-/opt/gaokao-sys-data}" +PORT="${PORT:-8501}" +KEY_PATH="$DATA_DIR/.ssh_key" +BASE="http://$GITEA_HOST:$GITEA_PORT" +API="$BASE/api/v1/repos/$GITEA_OWNER/$GITEA_REPO" + +# ---- 令牌: 环境变量优先, 否则交互静默输入(绕过管道 stdin) ---- +if [ -z "$GITEA_TOKEN" ]; then + read -s -p "请输入 Gitea 访问令牌(静默, 不回显): " GITEA_TOKEN < /dev/tty + echo "" +fi +: "${GITEA_TOKEN:?未输入令牌, 中止}" +TOKEN_CLEANED=0 + +# ---- 退出时自动删除一次性令牌 ---- +cleanup() { + if [ -n "$GITEA_TOKEN" ] && [ "$TOKEN_CLEANED" != "1" ]; then + if curl -fsS -X DELETE -H "Authorization: token $GITEA_TOKEN" \ + "$BASE/api/v1/user/tokens/$GITEA_OWNER/$TOKEN_NAME" >/dev/null 2>&1; then + echo "[OK] 一次性令牌已自动删除" + else + echo "[提示] 令牌自动删除失败(名字可能不同), 请管理员到 Gitea → 设置 → 应用 手动删除" + fi + fi +} +trap cleanup EXIT + +echo "==> [1/7] 检查 Docker" +command -v docker >/dev/null 2>&1 || { echo "[错误] 未安装 Docker"; exit 1; } + +echo "==> [2/7] 克隆代码(令牌认证)" +mkdir -p "$APP_DIR" +if [ ! -d "$APP_DIR/.git" ]; then + git clone "http://oauth2:$GITEA_TOKEN@$GITEA_HOST:$GITEA_PORT/$GITEA_OWNER/$GITEA_REPO.git" "$APP_DIR" +else + cd "$APP_DIR" && git pull +fi + +echo "==> [3/7] 生成部署密钥并自动加入 Gitea(API, 升级免密)" +mkdir -p "$DATA_DIR/data" +if [ ! -f "$KEY_PATH" ]; then + ssh-keygen -t rsa -b 4096 -f "$KEY_PATH" -N "" -q + PUB="$(cat "$KEY_PATH.pub")" + if curl -fsS -X POST -H "Authorization: token $GITEA_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"title\":\"$(hostname)-deploy\",\"key\":\"$PUB\",\"read_only\":true}" \ + "$API/keys" >/dev/null 2>&1; then + echo "[OK] 部署密钥已自动添加(只读)" + else + echo "[提示] 部署密钥添加失败: 到 Gitea → gaokao-sys → 设置 → 部署密钥 手动添加(只读):" + cat "$KEY_PATH.pub" + fi +fi +chmod 600 "$KEY_PATH" + +echo "==> [4/7] 构建镜像(首次较慢)" +cd "$APP_DIR" +docker build -t gaokao-sys:latest . + +echo "==> [5/7] 启动容器" +docker rm -f gaokao-sys >/dev/null 2>&1 || true +docker run -d --name gaokao-sys --restart=unless-stopped -p "$PORT:8501" \ + -v "$APP_DIR":/app \ + -v "$DATA_DIR/data":/app/data \ + -v "$KEY_PATH":/app/.ssh_key:ro \ + gaokao-sys:latest + +echo "==> [6/7] 验证" +sleep 10 +curl -sf "http://127.0.0.1:$PORT/_stcore/health" >/dev/null 2>&1 && echo "[OK] 服务健康" || echo "[警告] 服务未响应: docker logs gaokao-sys" + +echo "==> [7/7] 完成" +IP=$(hostname -I 2>/dev/null | awk '{print $1}') +echo " 访问: http://${IP:-<本机IP>}:$PORT" +echo " 升级: 系统内「数据管理 → 🔄 更新」(手动/全自动, 走只读部署密钥)"