Gitee + Linux 全自动部署系统搭建指南

Gitee + Linux 全自动部署系统搭建指南
版本: 1.0
环境: Nginx + PHP 8.x + Git
场景: 本地代码推送到 Gitee 后,Linux 服务器自动拉取并部署。
⚠️ 前置核心原则
- 敏感文件不入库:数据库配置 (
config.inc.php) 和上传目录 (usr/uploads) 必须忽略。 - 权限分离:部署脚本由 Web 用户 (
www-data) 执行,必须确保该用户有文件读写权限。 - 鉴权固化:在服务器端硬编码 Git 账号密码,彻底解决自动拉取时的密码验证失败问题。
第一阶段:本地开发环境准备 (Windows/Mac)
1. 配置忽略规则 (.gitignore)
在项目根目录创建 .gitignore,防止敏感文件泄露及覆盖服务器配置。
# --- 核心配置 (绝对禁止提交) ---
config.inc.php
database.php
.env
# --- 部署工具 (保护 Token) ---
webhook.php
deploy.sh
# --- 用户数据 (防止覆盖服务器图片) ---
/usr/uploads/*
!/usr/uploads/.gitkeep
# --- IDE 与系统垃圾文件 ---
.idea/
.vscode/
*.log
.DS_Store
Thumbs.db2. 清理 Git 缓存 (重要)
如果 config.inc.php 之前已经被提交过,必须执行以下命令将其从版本库移除(保留本地文件):
git rm --cached config.inc.php
git rm --cached webhook.php
git commit -m "Security: Remove sensitive files from tracking"
git push origin master第二阶段:服务器端 Git 配置 (Linux)
1. 初始化仓库
以 root 身份登录,克隆项目到 Web 根目录。
cd /var/www
# 首次克隆
git clone https://gitee.com/YOUR_USERNAME/YOUR_PROJECT.git typecho
cd typecho2. 硬编码凭证 (解决鉴权核心)
修改 .git/config 文件,将账号密码直接写入 URL,避免脚本执行时因无交互界面而报错。
nano .git/config找到 [remote "origin"] 部分,修改 url:
[remote "origin"]
# 格式说明:https://用户名:密码@gitee.com/用户名/项目名.git
# ⚠️ 注意:如果密码中包含 @,必须替换为 %40 (URL编码)
url = https://YOUR_PHONE_NUM:YOUR_PASSWORD@gitee.com/YOUR_USERNAME/YOUR_PROJECT.git
fetch = +refs/heads/*:refs/remotes/origin/*3. 忽略权限变更
避免 Linux/Windows 文件权限差异导致 Git 提示文件被修改。
git config core.filemode false第三阶段:部署脚本编写
在服务器项目根目录 (/var/www/typecho/) 创建以下两个文件。
1. 执行脚本 (deploy.sh)
#!/bin/bash
# --- 配置区 ---
BRANCH="master"
LOGFILE="deploy.log"
# 切换到脚本所在目录
cd "$(dirname "$0")" || exit
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOGFILE"
}
echo "" >> "$LOGFILE"
log "--- DEPLOY START ($BRANCH) ---"
# 1. 信任当前目录 (解决 Git 安全目录限制)
git config safe.directory "$(pwd)"
# 2. 拉取代码
log "[1/2] Pulling code..."
git checkout "$BRANCH" >> "$LOGFILE" 2>&1
# 尝试拉取,如果失败则强制重置
if git pull origin "$BRANCH" >> "$LOGFILE" 2>&1; then
log "Git pull success."
else
log "Git pull failed, trying force reset..."
git fetch --all >> "$LOGFILE" 2>&1
git reset --hard origin/"$BRANCH" >> "$LOGFILE" 2>&1
if [ $? -eq 0 ]; then
log "Force reset success."
else
log "Error: Force reset failed."
exit 1
fi
fi
# 3. 修正权限 (确保 Web 用户可读写)
log "[2/2] Fixing permissions..."
find . -type d -not -path "./.git*" -exec chmod 755 {} \;
find . -type f -not -path "./.git*" -exec chmod 644 {} \;
chmod +x deploy.sh
log "Permissions fixed."
log "--- DEPLOY FINISHED ---"
echo "Done."2. 接收入口 (webhook.php)
<?php
// ==========================================
// Gitee WebHook Receiver
// ==========================================
// ★ 设置密钥 (必须与 Gitee 后台填写的一致)
$secret = 'YOUR_WEBHOOK_PASSWORD';
// 获取 Token
$headers = getallheaders();
$token = $headers['X-Gitee-Token'] ?? $_SERVER['HTTP_X_GITEE_TOKEN'] ?? '';
// 鉴权
if ($token !== $secret) {
http_response_code(403);
die('🚫 Access Denied');
}
// 执行部署
echo "✅ Authorized. Deploying...\n";
// 2>&1 用于捕获标准错误输出
$output = shell_exec('cd ' . __DIR__ . ' && ./deploy.sh 2>&1');
echo "<pre>$output</pre>";
?>第四阶段:权限移交 (关键步骤)
由于之前的操作是 root 进行的,必须将文件所有权移交给 Web 服务器运行用户(通常是 www-data),否则 Webhook 触发时无权修改文件。
# 1. 修改目录所有者
chown -R www-data:www-data /var/www/typecho
# 2. 赋予脚本执行权限
chmod +x /var/www/typecho/deploy.sh第五阶段:Gitee 后台设置
- 进入 Gitee 项目 -\> 管理 -\> WebHooks。
- 添加 WebHook。
- URL:
http://你的域名或IP/webhook.php - WebHook 密码/签名密钥: 填写
webhook.php中设置的$secret。 - 事件: 勾选
Push。 - 点击 添加 并点击 测试,查看是否返回 200 状态码。
第六阶段:服务保活 (防重启失效)
确保服务器重启后,Web 服务能自动拉起,保证 Webhook 可用。
# 开启服务开机自启
systemctl enable nginx
systemctl enable mysql
# 根据实际 PHP 版本开启 (如 php8.2-fpm)
systemctl enable php8.2-fpm 第七阶段:数据库迁移与自动部署联动
1. 数据库迁移目录规范
- 迁移脚本统一放在 Typecho 项目根目录下的
db/migrations/目录。 - 文件命名建议采用时间前缀 + 描述的方式,方便排序与追踪,例如:
db/migrations/
├── 20251214_01_create_demo_migration_table.sql
├── 20251220_01_add_xxx_column.sql
└── 20251220_02_update_xxx_index.sql2. 迁移执行入口 (migrate.php)
- 入口脚本位于 Typecho 根目录:
migrate.php。 其核心行为为:
- 通过
config.inc.php初始化 Typecho,并获取数据库对象。 - 自动创建
schema_migrations表,用于记录已执行的迁移文件名。 - 只执行
db/migrations目录下「尚未记录」的.sql文件。 - 每执行成功一个迁移,就将文件名写入
schema_migrations,确保幂等性。
- 通过
在服务器或本地项目根目录执行:
php migrate.php典型输出示例:
Applied migration: 20251214_01_create_demo_migration_table.sql
Migrations complete.如果再次执行,且没有新的迁移文件,则会直接输出:
Migrations complete.3. 本地开发时的数据库变更流程
- 在本地数据库手动尝试 SQL 变更,确认无误。
- 将最终确认的 SQL 写入一个新的迁移文件,例如:
-- db/migrations/20251220_01_add_demo_column.sql
ALTER TABLE demo_migration_test
ADD COLUMN demo_note varchar(255) NOT NULL DEFAULT '';- 在本地 Typecho 根目录执行:
php migrate.php- 确认输出中有
Applied migration: 文件名,并在数据库中验证结构已生效。 - 将迁移文件纳入版本控制,随代码一起推送到 Gitee。
4. 服务器端自动部署中的迁移步骤
在服务器的 deploy.sh 中,完成代码拉取和权限修复后,追加一行执行迁移脚本的命令,即可把数据库结构更新纳入「自动部署流程」。
示例片段(仅保留关键部分,注意顺序):
# 2. 拉取代码
log "[1/3] Pulling code..."
git checkout "$BRANCH" >> "$LOGFILE" 2>&1
if git pull origin "$BRANCH" >> "$LOGFILE" 2>&1; then
log "Git pull success."
else
log "Git pull failed, trying force reset..."
git fetch --all >> "$LOGFILE" 2>&1
git reset --hard origin/"$BRANCH" >> "$LOGFILE" 2>&1
if [ $? -eq 0 ]; then
log "Force reset success."
else
log "Error: Force reset failed."
exit 1
fi
fi
# 3. 执行数据库迁移
log "[2/3] Running database migrations..."
php migrate.php >> "$LOGFILE" 2>&1
# 4. 修正权限 (确保 Web 用户可读写)
log "[3/3] Fixing permissions..."
find . -type d -not -path "./.git*" -exec chmod 755 {} \;
find . -type f -not -path "./.git*" -exec chmod 644 {} \;
chmod +x deploy.sh要点说明:
- 迁移必须在「代码已经更新完成」之后执行,否则可能会出现新代码依赖的表字段尚未创建的情况。
- 权限修复放在最后,确保迁移过程中可能产生的新文件(如日志)也有正确权限。
- 若迁移过程中发生错误,可直接在
deploy.log中查看php migrate.php的输出。
5. 推荐的整体开发与部署节奏
本地开发:
- 修改代码和 SQL。
- 将数据库变更整理为迁移 SQL 文件,放入
db/migrations/。 - 执行
php migrate.php测试并确认无误。 - 提交代码和迁移文件,推送到 Gitee。
服务器:
- 由 Gitee WebHook 触发
webhook.php。 webhook.php调用deploy.sh。deploy.sh依次执行:拉取代码 → 运行php migrate.php→ 修正权限。
- 由 Gitee WebHook 触发
这样可以保证:代码版本、数据库结构、服务器实际运行环境三者始终保持同步,并且所有数据库变更都有清晰可追踪的迁移文件记录。
常见问题排查
Error: Permission denied (publickey, password)
- 检查
.git/config中的 URL 是否正确,密码特殊字符是否已转义。
- 检查
Error: unable to unlink old 'xxx' 或 Permission denied
- 文件所有权不对。重新执行
chown -R www-data:www-data /var/www/typecho。
- 文件所有权不对。重新执行
Deploy.log 无记录
- 检查
webhook.php是否被正常访问,检查www-data是否有权写入deploy.log。
- 检查
1