172 lines
7.7 KiB
Bash
Executable File
172 lines
7.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# ════════════════════════════════════════════════════════════════
|
|
# 光湖 · 服务器标准模板部署脚本
|
|
# 将任意腾讯云服务器初始化为铸渊主控节点
|
|
# ════════════════════════════════════════════════════════════════
|
|
#
|
|
# 用法:
|
|
# sudo bash bootstrap.sh --gitea-url https://guanghulab.com \
|
|
# --api-token <TOKEN> \
|
|
# --runner-name <NAME>
|
|
#
|
|
# 此脚本会:
|
|
# 1. 更新系统 + 安装基础软件 (Node.js 20, PM2, Nginx, git, curl)
|
|
# 2. 创建 /data/guanghulab/ 目录结构
|
|
# 3. 从 Gitea 克隆仓库
|
|
# 4. 安装 Gitea Actions Runner
|
|
# 5. 启动 Secrets Vault (如当前是Gitea服务器则跳过)
|
|
# 6. 上报完成状态
|
|
#
|
|
# ════════════════════════════════════════════════════════════════
|
|
|
|
set -euo pipefail
|
|
|
|
# ─── 配置 ─────────────────────────────────────────────────────
|
|
GITEA_URL=""
|
|
API_TOKEN=""
|
|
RUNNER_NAME=""
|
|
DATA_DIR="/data/guanghulab"
|
|
LOG_DIR="${DATA_DIR}/logs"
|
|
GITEA_OWNER="bingshuo"
|
|
GITEA_REPO="guanghulab"
|
|
|
|
# 颜色
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
log_info() { echo -e "${GREEN}[✓]${NC} $*"; }
|
|
log_step() { echo -e "${CYAN}[→]${NC} $*"; }
|
|
log_error() { echo -e "${RED}[✗]${NC} $*"; }
|
|
|
|
# ─── 解析参数 ─────────────────────────────────────────────────
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
--gitea-url) GITEA_URL="$2"; shift 2 ;;
|
|
--api-token) API_TOKEN="$2"; shift 2 ;;
|
|
--runner-name) RUNNER_NAME="$2"; shift 2 ;;
|
|
--data-dir) DATA_DIR="$2"; shift 2 ;;
|
|
*) log_error "未知参数: $1"; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$GITEA_URL" || -z "$API_TOKEN" ]]; then
|
|
log_error "必须提供 --gitea-url 和 --api-token"
|
|
exit 1
|
|
fi
|
|
|
|
RUNNER_NAME="${RUNNER_NAME:-zhuyuan-runner-$(hostname | tr '[:upper:]' '[:lower:]')}"
|
|
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}"
|
|
echo -e "${CYAN} 光湖 · 服务器标准模板部署${NC}"
|
|
echo -e "${CYAN} 目标: $(hostname) · $(curl -sf ifconfig.me 2>/dev/null || echo 'IP未知')${NC}"
|
|
echo -e "${CYAN}═══════════════════════════════════════════════════════${NC}"
|
|
|
|
# ─── 1. 系统更新 ──────────────────────────────────────────────
|
|
log_step "更新系统..."
|
|
apt update && apt upgrade -y
|
|
|
|
# ─── 2. 安装基础软件 ──────────────────────────────────────────
|
|
log_step "安装基础软件..."
|
|
apt install -y curl git nginx ufw xz-utils
|
|
|
|
# Node.js 20
|
|
if ! command -v node &>/dev/null || [[ "$(node -v)" != v20* ]]; then
|
|
log_step "安装 Node.js 20..."
|
|
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
|
apt install -y nodejs
|
|
fi
|
|
log_info "Node.js: $(node -v)"
|
|
|
|
# PM2
|
|
if ! command -v pm2 &>/dev/null; then
|
|
npm install -g pm2
|
|
fi
|
|
log_info "PM2: $(pm2 -v)"
|
|
|
|
# ─── 3. 目录结构 ──────────────────────────────────────────────
|
|
log_step "创建目录结构..."
|
|
mkdir -p "${DATA_DIR}"/{logs,data,cos-bridge,secrets-vault,scripts}
|
|
log_info "数据目录: ${DATA_DIR}"
|
|
|
|
# ─── 4. 克隆仓库 ──────────────────────────────────────────────
|
|
if [[ ! -d "${DATA_DIR}/guanghulab/.git" ]]; then
|
|
log_step "从 Gitea 克隆仓库..."
|
|
git clone "https://${GITEA_OWNER}:${API_TOKEN}@${GITEA_URL#https://}/${GITEA_OWNER}/${GITEA_REPO}.git" \
|
|
"${DATA_DIR}/guanghulab"
|
|
log_info "仓库克隆完成"
|
|
else
|
|
log_info "仓库已存在,拉取最新..."
|
|
cd "${DATA_DIR}/guanghulab" && git pull
|
|
fi
|
|
|
|
# ─── 5. 安装 Runner ───────────────────────────────────────────
|
|
log_step "安装 Gitea Actions Runner..."
|
|
cd "${DATA_DIR}/guanghulab"
|
|
bash scripts/gitea-runner/install-runner.sh \
|
|
--token "$API_TOKEN" \
|
|
--name "$RUNNER_NAME" \
|
|
--mode host
|
|
|
|
# ─── 6. Secrets Vault ─────────────────────────────────────────
|
|
log_step "检查 Secrets Vault..."
|
|
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
log_info "Secrets Vault 已运行"
|
|
else
|
|
log_step "启动 Secrets Vault..."
|
|
cd "${DATA_DIR}/guanghulab/server/secrets-vault"
|
|
npm install --production 2>/dev/null || true
|
|
pm2 start server.js --name guanghulab-vault --max-memory-restart 128M
|
|
pm2 save
|
|
log_info "Secrets Vault 已启动"
|
|
fi
|
|
|
|
# ─── 7. 防火墙 ────────────────────────────────────────────────
|
|
log_step "配置防火墙..."
|
|
ufw allow 22/tcp # SSH
|
|
ufw allow 80/tcp # HTTP
|
|
ufw allow 443/tcp # HTTPS
|
|
ufw --force enable
|
|
log_info "防火墙已配置"
|
|
|
|
# ─── 8. 上报状态 ──────────────────────────────────────────────
|
|
log_step "上报部署状态..."
|
|
REPORT_FILE="${DATA_DIR}/logs/bootstrap-$(date +%Y%m%d-%H%M%S).json"
|
|
cat > "$REPORT_FILE" << EOF
|
|
{
|
|
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
"hostname": "$(hostname)",
|
|
"ip": "$(curl -sf ifconfig.me 2>/dev/null || echo unknown)",
|
|
"os": "$(uname -srm)",
|
|
"cpu_cores": $(nproc),
|
|
"memory_mb": $(free -m | awk '/Mem:/ {print $2}'),
|
|
"node_version": "$(node -v)",
|
|
"runner_name": "${RUNNER_NAME}",
|
|
"data_dir": "${DATA_DIR}",
|
|
"services": {
|
|
"nginx": "$(systemctl is-active nginx 2>/dev/null || echo unknown)",
|
|
"gitea_runner": "$(systemctl is-active gitea-runner 2>/dev/null || echo unknown)",
|
|
"vault": "$(curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1 && echo active || echo inactive)"
|
|
},
|
|
"deployed_by": "铸渊 · ICE-GL-ZY001"
|
|
}
|
|
EOF
|
|
log_info "状态报告: ${REPORT_FILE}"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
|
echo -e "${GREEN} 服务器模板部署完成!${NC}"
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|
|
echo ""
|
|
echo " 服务器: $(hostname)"
|
|
echo " Runner: ${RUNNER_NAME}"
|
|
echo " 数据目录: ${DATA_DIR}"
|
|
echo " Vault: $(curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1 && echo '✅ 运行中' || echo '❌ 未运行')"
|
|
echo " Nginx: $(systemctl is-active nginx 2>/dev/null || echo unknown)"
|
|
echo ""
|
|
echo " 此服务器已纳入铸渊主控体系"
|
|
echo " 铸渊 · ICE-GL-ZY001 · TCS-0002∞"
|
|
echo -e "${GREEN}═══════════════════════════════════════════════════════${NC}"
|