添加自动部署配置
- 服务器一键配置脚本 - 部署脚本 (支持测试/正式环境) - Webhook 接收器 - 完整使用文档
This commit is contained in:
@@ -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
|
||||
```
|
||||
@@ -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 "=========================================="
|
||||
@@ -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'
|
||||
<?php
|
||||
const SECRET = 'kb-web-webhook-secret-2024';
|
||||
const DEPLOY_SCRIPT = '/var/www/webhook/deploy.sh';
|
||||
const LOG_FILE = '/var/log/webhook.log';
|
||||
|
||||
function log_msg($msg) {
|
||||
file_put_contents(LOG_FILE, "[".date('Y-m-d H:i:s')."] $msg\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
function verify_signature($payload, $signature) {
|
||||
$expected = 'sha256=' . hash_hmac('sha256', $payload, SECRET);
|
||||
return hash_equals($expected, $signature);
|
||||
}
|
||||
|
||||
log_msg("收到 webhook 请求");
|
||||
$payload = file_get_contents('php://input');
|
||||
$headers = function_exists('getallheaders') ? getallheaders() : [];
|
||||
|
||||
$signature = '';
|
||||
foreach ($headers as $k => $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 "=========================================="
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* Gitea Webhook 接收器
|
||||
* 路径: /var/www/webhook/receiver.php
|
||||
* 访问: https://webhook.micecola.top/kb-web.php
|
||||
*/
|
||||
|
||||
// 配置
|
||||
const SECRET = 'kb-web-webhook-secret-2024'; // 与 Gitea webhook 配置的密钥一致
|
||||
const DEPLOY_SCRIPT = '/var/www/webhook/deploy.sh';
|
||||
const LOG_FILE = '/var/log/webhook.log';
|
||||
|
||||
// 记录日志
|
||||
function log_msg($msg) {
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
file_put_contents(LOG_FILE, "[$timestamp] $msg\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
function verify_signature($payload, $signature) {
|
||||
$expected = 'sha256=' . hash_hmac('sha256', $payload, SECRET);
|
||||
return hash_equals($expected, $signature);
|
||||
}
|
||||
|
||||
// 主逻辑
|
||||
log_msg("收到 webhook 请求");
|
||||
|
||||
$payload = file_get_contents('php://input');
|
||||
$headers = getallheaders();
|
||||
|
||||
// 验证 Gitea 签名
|
||||
$signature = $headers['X-Gitea-Signature'] ?? $headers['X-Gitea-Signature-Sha256'] ?? '';
|
||||
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'] ?? '');
|
||||
$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);
|
||||
Reference in New Issue
Block a user