diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..ce61fc8 --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,104 @@ +# kb-web 自动部署配置 + +## 架构 + +``` +本地 push → Gitea (192.168.1.22) → Webhook → micecola.top + ├── /var/www/kb-web-test (测试 :8080) + └── /var/www/kb-web-prod (正式域名) +``` + +## 快速配置 + +### 第一步:在服务器执行配置脚本 + +```bash +# SSH 登录服务器 +ssh root@micecola.top + +# 下载并执行配置脚本 +curl -fsSL https://raw.githubusercontent.com/你的仓库/deploy/setup-server.sh | bash + +# 或者直接复制脚本内容执行 +``` + +### 第二步:添加 Gitea 部署密钥 + +服务器执行后会显示一个公钥,将它添加到 Gitea: + +1. 打开 https://192.168.1.22 用户设置 → SSH Keys +2. 或在仓库设置 → Deploy Keys +3. 粘贴公钥内容 + +### 第三步:配置 Gitea Webhook + +在 Gitea 仓库 `kb-web` 的设置中: + +| 配置项 | 值 | +|--------|-----| +| URL | `http://micecola.top:8080/webhook/receiver.php` | +| 密钥 | `kb-web-webhook-secret-2024` | +| 触发事件 | Push | +| 分支过滤 | main | + +### 第四步:测试 + +```bash +# 本地修改后推送 +git push origin main + +# 查看服务器日志 +ssh root@micecola.top "tail -f /var/log/webhook.log" +``` + +## 访问地址 + +| 环境 | 地址 | +|------|------| +| 测试 | http://micecola.top:8080 | +| 正式 | https://kb.micecola.top (需配置域名) | + +## 手动部署 + +```bash +# 测试环境 +/var/www/webhook/deploy.sh test main + +# 正式环境 +/var/www/webhook/deploy.sh prod main +``` + +## 正式环境部署流程 + +推荐流程:先测试环境验证 → 再手动部署正式环境 + +```bash +# 1. push 自动部署到测试环境 +git push origin main + +# 2. 验证测试环境 OK +# 访问 http://micecola.top:8080 + +# 3. 手动部署到正式环境 +ssh root@micecola.top "/var/www/webhook/deploy.sh prod main" +``` + +## 文件说明 + +``` +deploy/ +├── setup-server.sh # 服务器一键配置脚本 +├── deploy.sh # 部署脚本 (部署到服务器 /var/www/webhook/) +├── webhook-receiver.php # Webhook 接收器 (部署到服务器) +└── README.md # 本文档 +``` + +## 回滚 + +```bash +# 查看备份 +ls /var/www/kb-web-test-backups/ + +# 恢复备份 +tar -xzf /var/www/kb-web-test-backups/backup_xxx.tar.gz -C /var/www/kb-web-test +``` diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100644 index 0000000..e81c7d7 --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# kb-web 自动部署脚本 +# 用法: ./deploy.sh [test|prod] [branch] + +set -e + +DEPLOY_ENV=${1:-test} +BRANCH=${2:-main} +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") + +# 配置 +case $DEPLOY_ENV in + test) + DEPLOY_DIR="/var/www/kb-web-test" + BACKUP_DIR="/var/www/kb-web-test-backups" + ;; + prod) + DEPLOY_DIR="/var/www/kb-web-prod" + BACKUP_DIR="/var/www/kb-web-prod-backups" + ;; + *) + echo "用法: $0 [test|prod] [branch]" + exit 1 + ;; +esac + +REPO_URL="ssh://sc-gitea@192.168.1.22:2223/starmen1265/kb-web.git" +LOG_FILE="/var/log/kb-web-deploy.log" + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "========== 开始部署 $DEPLOY_ENV 环境 ==========" +log "分支: $BRANCH" +log "目标目录: $DEPLOY_DIR" + +# 创建目录 +mkdir -p "$DEPLOY_DIR" "$BACKUP_DIR" "$(dirname "$LOG_FILE")" + +# 备份当前版本 +if [ -d "$DEPLOY_DIR/.git" ]; then + log "备份当前版本..." + CURRENT_COMMIT=$(cd "$DEPLOY_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "unknown") + tar -czf "$BACKUP_DIR/backup_${CURRENT_COMMIT}_${TIMESTAMP}.tar.gz" -C "$DEPLOY_DIR" . 2>/dev/null || true + # 只保留最近5个备份 + cd "$BACKUP_DIR" && ls -t | tail -n +6 | xargs -r rm -f +fi + +# 拉取代码 +if [ -d "$DEPLOY_DIR/.git" ]; then + log "更新代码..." + cd "$DEPLOY_DIR" + git fetch origin + git reset --hard "origin/$BRANCH" +else + log "克隆代码..." + git clone -b "$BRANCH" "$REPO_URL" "$DEPLOY_DIR" + cd "$DEPLOY_DIR" +fi + +# 设置权限 +log "设置权限..." +chown -R www-data:www-data "$DEPLOY_DIR" 2>/dev/null || chown -R nginx:nginx "$DEPLOY_DIR" 2>/dev/null || true +find "$DEPLOY_DIR" -type d -exec chmod 755 {} \; +find "$DEPLOY_DIR" -type f -exec chmod 644 {} \; + +# 记录部署信息 +DEPLOY_INFO="$DEPLOY_DIR/.deploy_info" +cat > "$DEPLOY_INFO" << EOF +环境: $DEPLOY_ENV +分支: $BRANCH +提交: $(git rev-parse HEAD) +时间: $(date '+%Y-%m-%d %H:%M:%S') +部署者: webhook +EOF + +log "部署完成!" +log "提交: $(git log -1 --oneline)" +log "==========================================" diff --git a/deploy/setup-server.sh b/deploy/setup-server.sh new file mode 100644 index 0000000..051ef36 --- /dev/null +++ b/deploy/setup-server.sh @@ -0,0 +1,271 @@ +#!/bin/bash +# 服务器一键配置脚本 +# 在 micecola.top 上执行此脚本 + +set -e + +echo "==========================================" +echo " kb-web 自动部署环境配置" +echo "==========================================" + +# 创建目录结构 +echo "[1/5] 创建目录结构..." +mkdir -p /var/www/kb-web-test +mkdir -p /var/www/kb-web-prod +mkdir -p /var/www/kb-web-test-backups +mkdir -p /var/www/kb-web-prod-backups +mkdir -p /var/www/webhook +mkdir -p /var/log + +# 创建部署脚本 +echo "[2/5] 创建部署脚本..." +cat > /var/www/webhook/deploy.sh << 'DEPLOY_SCRIPT' +#!/bin/bash +set -e + +DEPLOY_ENV=${1:-test} +BRANCH=${2:-main} +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") + +case $DEPLOY_ENV in + test) DEPLOY_DIR="/var/www/kb-web-test"; BACKUP_DIR="/var/www/kb-web-test-backups" ;; + prod) DEPLOY_DIR="/var/www/kb-web-prod"; BACKUP_DIR="/var/www/kb-web-prod-backups" ;; + *) echo "用法: $0 [test|prod] [branch]"; exit 1 ;; +esac + +REPO_URL="ssh://sc-gitea@192.168.1.22:2223/starmen1265/kb-web.git" +LOG_FILE="/var/log/kb-web-deploy.log" + +log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"; } + +log "开始部署 $DEPLOY_ENV 环境, 分支: $BRANCH" +mkdir -p "$DEPLOY_DIR" "$BACKUP_DIR" + +if [ -d "$DEPLOY_DIR/.git" ]; then + log "备份当前版本..." + CURRENT_COMMIT=$(cd "$DEPLOY_DIR" && git rev-parse --short HEAD 2>/dev/null || echo "unknown") + tar -czf "$BACKUP_DIR/backup_${CURRENT_COMMIT}_${TIMESTAMP}.tar.gz" -C "$DEPLOY_DIR" . 2>/dev/null || true + cd "$BACKUP_DIR" && ls -t | tail -n +6 | xargs -r rm -f + + log "更新代码..." + cd "$DEPLOY_DIR" + git fetch origin + git reset --hard "origin/$BRANCH" +else + log "克隆代码..." + git clone -b "$BRANCH" "$REPO_URL" "$DEPLOY_DIR" + cd "$DEPLOY_DIR" +fi + +log "设置权限..." +chown -R www-data:www-data "$DEPLOY_DIR" 2>/dev/null || chown -R nginx:nginx "$DEPLOY_DIR" 2>/dev/null || true + +DEPLOY_INFO="$DEPLOY_DIR/.deploy_info" +cat > "$DEPLOY_INFO" << EOF +环境: $DEPLOY_ENV +分支: $BRANCH +提交: $(git rev-parse HEAD) +时间: $(date '+%Y-%m-%d %H:%M:%S') +EOF + +log "部署完成: $(git log -1 --oneline)" +DEPLOY_SCRIPT + +chmod +x /var/www/webhook/deploy.sh + +# 创建 webhook 接收器 +echo "[3/5] 创建 webhook 接收器..." +cat > /var/www/webhook/receiver.php << 'RECEIVER_PHP' + $v) { + if (strtolower($k) === 'x-gitea-signature' || strtolower($k) === 'x-gitea-signature-sha256') { + $signature = $v; + break; + } +} + +if (!verify_signature($payload, $signature)) { + log_msg("签名验证失败"); + http_response_code(401); + echo json_encode(['error' => 'Invalid signature']); + exit; +} + +$data = json_decode($payload, true); +$repo = $data['repository']['name'] ?? ''; +$branch = basename($data['ref'] ?? ''); + +log_msg("仓库: $repo, 分支: $branch"); + +if ($repo !== 'kb-web') { + echo json_encode(['status' => 'ignored']); + exit; +} + +$env = 'test'; +log_msg("开始部署到 $env"); +exec(sprintf('%s %s %s 2>&1', DEPLOY_SCRIPT, $env, $branch), $output, $ret); + +header('Content-Type: application/json'); +echo json_encode(['status' => $ret === 0 ? 'success' : 'failed', 'output' => $output]); +RECEIVER_PHP + +# 创建 SSH 密钥用于拉取代码 +echo "[4/5] 配置 SSH 密钥..." +mkdir -p ~/.ssh +chmod 700 ~/.ssh + +# 如果没有部署密钥,创建一个 +if [ ! -f ~/.ssh/id_rsa_kb_deploy ]; then + ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_kb_deploy -N "" -C "kb-deploy@micecola" + echo "" + echo "==========================================" + echo " 请将以下公钥添加到 Gitea 部署密钥:" + echo "==========================================" + cat ~/.ssh/id_rsa_kb_deploy.pub + echo "==========================================" +fi + +# 配置 SSH config +cat >> ~/.ssh/config << 'SSH_CONFIG' + +# kb-web 部署 +Host sc-gitea + HostName 192.168.1.22 + Port 2223 + User sc-gitea + IdentityFile ~/.ssh/id_rsa_kb_deploy + StrictHostKeyChecking no +SSH_CONFIG + +chmod 600 ~/.ssh/config + +# 配置 Nginx +echo "[5/5] 配置 Nginx..." + +# 测试环境 +cat > /etc/nginx/sites-available/kb-web-test.conf << 'NGINX_CONF' +server { + listen 8080; + server_name _; + root /var/www/kb-web-test; + index index.php index.html; + + access_log /var/log/nginx/kb-web-test.access.log; + error_log /var/log/nginx/kb-web-test.error.log; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/run/php/php-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\. { + deny all; + } +} +NGINX_CONF + +# 正式环境 (需要你配置 SSL) +cat > /etc/nginx/sites-available/kb-web-prod.conf << 'NGINX_CONF' +server { + listen 80; + server_name kb.micecola.top; # 修改为你的域名 + + root /var/www/kb-web-prod; + index index.php index.html; + + access_log /var/log/nginx/kb-web-prod.access.log; + error_log /var/log/nginx/kb-web-prod.error.log; + + # 强制 HTTPS (配置 SSL 后启用) + # return 301 https://$server_name$request_uri; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass unix:/run/php/php-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\. { + deny all; + } +} + +# HTTPS 配置 (需要 SSL 证书后启用) +# server { +# listen 443 ssl http2; +# server_name kb.micecola.top; +# +# ssl_certificate /etc/nginx/ssl/kb.micecola.top.crt; +# ssl_certificate_key /etc/nginx/ssl/kb.micecola.top.key; +# +# root /var/www/kb-web-prod; +# index index.php index.html; +# +# location / { +# try_files $uri $uri/ /index.php?$query_string; +# } +# +# location ~ \.php$ { +# fastcgi_pass unix:/run/php/php-fpm.sock; +# fastcgi_index index.php; +# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +# include fastcgi_params; +# } +# } +NGINX_CONF + +# 启用站点 +ln -sf /etc/nginx/sites-available/kb-web-test.conf /etc/nginx/sites-enabled/ +ln -sf /etc/nginx/sites-available/kb-web-prod.conf /etc/nginx/sites-enabled/ + +# 测试并重载 Nginx +nginx -t && systemctl reload nginx + +echo "" +echo "==========================================" +echo " 配置完成!" +echo "==========================================" +echo "" +echo "下一步操作:" +echo "1. 将上面的部署公钥添加到 Gitea 仓库的 Deploy Keys" +echo "2. 在 Gitea 仓库设置中添加 Webhook:" +echo " - URL: http://micecola.top:8080/webhook/receiver.php" +echo " - 密钥: kb-web-webhook-secret-2024" +echo " - 触发: Push 事件" +echo "3. 测试环境访问: http://micecola.top:8080" +echo "4. 正式环境域名: kb.micecola.top (需配置 DNS 和 SSL)" +echo "" +echo "手动部署命令:" +echo " 测试环境: /var/www/webhook/deploy.sh test main" +echo " 正式环境: /var/www/webhook/deploy.sh prod main" +echo "==========================================" diff --git a/deploy/webhook-receiver.php b/deploy/webhook-receiver.php new file mode 100644 index 0000000..6cd48f4 --- /dev/null +++ b/deploy/webhook-receiver.php @@ -0,0 +1,78 @@ + 'Invalid signature']); + exit; +} + +$data = json_decode($payload, true); +$repo = $data['repository']['name'] ?? ''; +$branch = basename($data['ref'] ?? ''); +$commit = $data['after'] ?? ''; + +log_msg("仓库: $repo, 分支: $branch, 提交: $commit"); + +// 只处理 kb-web 仓库的 main 分支 +if ($repo !== 'kb-web') { + log_msg("忽略非目标仓库: $repo"); + echo json_encode(['status' => 'ignored', 'reason' => 'not target repo']); + exit; +} + +// 根据分支决定部署环境 +$env = 'test'; // 默认测试环境 +if ($branch === 'main' || $branch === 'master') { + // main 分支也先部署到测试环境 + // 正式环境需要手动触发 + $env = 'test'; +} + +// 执行部署脚本 +log_msg("开始部署到 $env 环境"); +$cmd = sprintf('%s %s %s 2>&1', DEPLOY_SCRIPT, $env, $branch); +exec($cmd, $output, $return_var); + +log_msg("部署输出: " . implode("\n", $output)); +log_msg("部署结果: " . ($return_var === 0 ? '成功' : '失败')); + +// 返回结果 +header('Content-Type: application/json'); +echo json_encode([ + 'status' => $return_var === 0 ? 'success' : 'failed', + 'env' => $env, + 'branch' => $branch, + 'commit' => $commit, + 'output' => $output +], JSON_UNESCAPED_UNICODE);