Skip to content

个人博客自建指南(7):自动化部署 —— git push 直达线上(上)

前言

第6篇我们用手动 build + scp 的方式上线了博客。操作不复杂,但每次写完文章都要重复这三步:

powershell
cd F:\web\jiejinx-blog
pnpm run build
scp -r docs/.vitepress/dist/* ecs-user@你的IP:/var/www/html/blog/

久了难免觉得繁琐。理想的流程是:本地写完 md、配好导航,git push,剩下的事情交给机器

这篇就来实现它。完成后,你的博客更新流程将简化为:

bash
git add .
git commit -m "新增:树莓派 DDNS 配置"
git push

等待 20-40 秒,刷新浏览器,新内容已上线。

一、方案选择

方案优点缺点推荐度
GitHub Actions免费,配置简单GitHub 国内访问不稳
ECS bare repo + hook零外网依赖需自建 Git 远程仓,多一套维护⚠️ 备选
Gitee + ECS WebHookGitee 已是线上仓,WebHook 触发 ECS 执行,职责清晰需 ECS 反向代理配置收 WebHook✅ 推荐

你已经在用 Gitee 作为线上仓库,那就不需要再自建 Git 服务。让 Gitee 当触发器,ECS 当执行者,本地只跟 Gitee 打交道 —— 这是最简洁的模型。

架构总览

本地写 md
  → git push gitee
    → Gitee 收到 push,触发 WebHook(POST 到 ECS 的一个接口)
      → ECS 收到请求,验证 token
        → 拉 Gitee 最新代码到工作目录
        → pnpm install + pnpm run build
        → rsync dist/ → /var/www/html/blog/

全程本地不碰 ECS,ECS 不裸跑 Git 服务,Gitee 做中转和触发器

前置条件

  • 已完成第6篇的全部步骤(ECS 上有 Nginx、博客已手动部署成功、域名已解析)
  • 你的博客项目已托管在 Gitee 仓库(公开或私有均可)
  • 本地 Git remote 已指向 Gitee

二、ECS 安装部署环境

第6篇的手动部署只需要 Nginx ,不涉及 Node.js。但自动化部署需要在 ECS 上执行 pnpm installpnpm run build,因此,必须为 ECS 安装 Node.js 运行时环境

第2篇介绍的 fnm + pnpm 安装方法是针对 Windows 本地环境的。ECS 一般安装的是 Linux 系统(CentOS / Ubuntu / Alibaba Cloud Linux),不能直接照搬,需要单独配置。

2.1 安装 fnm(Fast Node Manager)

打开终端,登录 ECS:

bash
ssh ecs-user@你的ECS公网IP

先在 ECS 服务器上执行一条命令确认 CPU 架构,决定下载fnm客户端:

bash
uname -m
  • 输出 x86_64​ → 下 fnm-linux.zip(通用 64 位 Intel/AMD 架构,绝大多数云服务器都是这个)
  • 输出 aarch64(或 arm64)→ 下 fnm-arm64.zip(ARM 64 位架构,如部分 ARM 型 ECS、树莓派 4B 等)
  • 输出 armv7l​ → 下 fnm-arm32.zip(32 位 ARM,很少见了)

执行以下命令, 先安装 unzip 解压工具:

bash
# 查询系统名词, 查看结果都 NAME 值
cat /etc/*release

# 根据系统名 执行 对应的安装解压工具 命令:

# Ubuntu/Debian:
sudo apt update && sudo apt install unzip -y

# CentOS/Alibaba Cloud Linux:
sudo yum install unzip -y

安装 fnm ( 以 x86_64 架构为例,按架构修改 zip包名 ):

bash
# 进入临时目录
cd /tmp

# 下载fnm安装包
curl -LO https://777.z321.cc.cd/https://github.com/Schniz/fnm/releases/download/v1.39.0/fnm-linux.zip   

#下载后解压安装
unzip fnm-linux.zip
chmod +x fnm
sudo mv fnm /usr/local/bin/

# 清理安装包相关文件
rm -f fnm-linux.zip fnm LICENSE README.md

上述下载链接中,若代理超时 代理站点可进行替换,通过代理查询站查询可用节点地址替换。
例如: https://gh.llkk.cc/https://github.com/....
替换为: https://777.z321.cc.cd/https://github.com/....

代理查询站:https://github.akams.cn/

安装完成后,根据终端提示,将 fnm 添加到 shell 配置中:

bash
# 查看你当前用的是哪种 Shell
echo $SHELL

#  如果你使用的是 Bash:
echo 'eval "$(fnm env --use-on-cd)"' >> ~/.bashrc
source ~/.bashrc

#  如果使用的是 Zsh(部分系统默认): 
echo 'eval "$(fnm env --use-on-cd)"' >> ~/.zshrc
source ~/.zshrc

验证安装:

bash
fnm --version
# 预期输出 fnm 1.39.0

2.2 安装 Node.js 24

bash
fnm install 24

# 安装完成后执行:
fnm default 24

验证安装:

bash
node -v
# 应输出 v24.x.x

npm -v
# 应输出 11.x.x

2.3 配置 npm 国内镜像源

bash
npm config set registry https://registry.npmmirror.com

2.4 安装 pnpm

bash
npm install -g pnpm

pnpm --version
# 应输出 11.x.x

2.5 配置 pnpm 国内镜像源(加速依赖安装)

bash
pnpm config set registry https://registry.npmmirror.com

这一步可选,但推荐配置。ECS 如果在北京/上海区域,从 npmmirror 拉包速度远快于官方源。

2.6 配置 pnpm 环境变量

bash
pnpm setup

source /home/ecs-user/.bashrc

2.7 验证构建能力

找一个临时目录,测试 pnpm 是否能正常工作:

bash
mkdir ~/test-pnpm && cd ~/test-pnpm
echo '{"name":"test"}' > package.json
pnpm add lodash

如果安装成功,说明 Node.jspnpm 环境就绪。

完成后删除测试目录:

bash
cd ~ && rm -rf ~/test-pnpm

三、ECS 上准备部署脚本

3.1 生成token

WebHook 的 URL 是暴露在公网上的(即使走 Nginx 反代,也是一个公开可访问的地址)。如果不加校验,任何人只要知道你的 WebHook 地址,就可以触发部署脚本,可能导致:

  • 恶意代码被拉取并执行
  • 频繁触发部署耗尽服务器资源
  • 博客内容被恶意篡改

我们需要引入引入随机 tokentoken 相当于一把钥匙——只有持有正确 token 的请求才会被放行。没有 token 的人即使知道 WebHook 地址,也无法触发部署。 第一步:生成随机 token 在 ECS 上执行:

bash
openssl rand -hex 16

输出类似:

3f8a2c1b9e4d7f0a5c3b8e2d1f6a4c9b

这串字符就是你的 token。

3.2 创建部署脚本

复制以下所有命令 到 ECS 服务器中 执行:

⚠️ 复制前修改:
⚠️ 以下命令文本中 GIT_REPO=git@gitee.com:你的用户名/jiejinx-blog.git 这里替换为你的码云项目仓库ssh链接后 再复制命令执行
⚠️ EXPECTED_TOKEN="你的随机token", 这里的 token 需要自己提前生成并替换

bash
tee /home/ecs-user/deploy-blog.sh > /dev/null << 'SCRIPT'
#!/bin/bash
set -e

# ⚠️ 目录配置区(按你的实际情况修改)
GIT_REPO=git@gitee.com:你的用户名/jiejinx-blog.git  
WORK_DIR=/var/www/jiejinx-blog
DIST_DIR=/var/www/html/blog
BRANCH=master
LOG_FILE=/home/ecs-user/deploy.log

# ⚠️ Token 配置
EXPECTED_TOKEN="你的随机token"
TOKEN="$1"

# 日志文件超过 1000 行时自动清理前半部分
if [ -f "$LOG_FILE" ] && [ "$(wc -l < "$LOG_FILE")" -gt 1000 ]; then
  tail -n 500 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE"
fi

# Token 校验
if [ "$TOKEN" != "$EXPECTED_TOKEN" ]; then
  echo "❌ token 校验失败" | tee -a "$LOG_FILE"
  exit 1
fi

{
  echo "========================================"
  echo "🚀 开始部署:$(date '+%Y-%m-%d %H:%M:%S')"
} >> "$LOG_FILE"

# 1. 拉取最新代码
if [ ! -d "$WORK_DIR/.git" ]; then
  echo "首次部署,clone 仓库..." | tee -a "$LOG_FILE"
  git clone "$GIT_REPO" "$WORK_DIR"
  cd "$WORK_DIR"
else
  cd "$WORK_DIR"
  git fetch origin "$BRANCH"
  git reset --hard "origin/$BRANCH"
fi

echo "✅ 代码更新完成" | tee -a "$LOG_FILE"

# 2. 安装依赖
pnpm install --frozen-lockfile >> "$LOG_FILE" 2>&1
echo "✅ 依赖安装完成" | tee -a "$LOG_FILE"

# 3. 构建静态文件
pnpm run build >> "$LOG_FILE" 2>&1
echo "✅ 构建完成" | tee -a "$LOG_FILE"

# 4. 同步到 Nginx 目录
rsync -a --delete "$WORK_DIR/docs/.vitepress/dist/" "$DIST_DIR/"
echo "✅ 同步完成" | tee -a "$LOG_FILE"

# 5. 记录版本号
COMMIT_HASH=$(git rev-parse --short HEAD)
echo "📝 版本: $COMMIT_HASH ($BRANCH)" | tee -a "$LOG_FILE"
echo "🎉 部署完成:$(date '+%Y-%m-%d %H:%M:%S')" | tee -a "$LOG_FILE"
echo "========================================" >> "$LOG_FILE"
SCRIPT

3.3 加执行权限

bash
# 创建并授权工作目录
sudo mkdir -p /var/www/jiejinx-blog
sudo chown -R ecs-user:ecs-user /var/www/jiejinx-blog
#检查目录授权
ls -ld /var/www/jiejinx-blog

# 确认 Nginx 目录权限
sudo mkdir -p /var/www/html/blog
sudo chown -R ecs-user:ecs-user /var/www/html/blog
#检查目录授权
ls -ld /var/www/html/blog

# 授权脚本运行权限
chmod +x /home/ecs-user/deploy-blog.sh

3.4 私有仓库处理(开源仓库可跳过)

Gitee 私有仓库 clone/pull 需要认证。推荐使用 SSH 部署密钥。

3.4.1 在 ECS 上生成 SSH 密钥对(如果已有则跳过)

bash
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""

查看公钥:

bash
cat ~/.ssh/id_ed25519.pub

3.4.2 配置公钥

登录码云,打开 码云Gitee 仓库 → 管理​ → 部署公钥​管理 → 添加公钥,粘贴公钥内容,勾选“授予只读权限”

3.4.3 连通性验证

部署脚本通过 SSH 协议从 Gitee 拉取代码时,如果是首次连接,SSH 会提示确认主机指纹。由于后续的部署脚本是非交互式运行的,无法响应这个提示,会导致连接被拒绝。
提前将 Gitee 的主机指纹添加到 known_hosts 中,可以跳过这个确认步骤。

执行以下命令:

bash
# 添加 Gitee 主机指纹到 known_hosts

ssh-keyscan -t rsa gitee.com >> ~/.ssh/known_hosts

验证连通性:

bash
ssh -T git@gitee.com

如果返回以下内容,说明 SSH 连通性正常:

Hi Anonymous (DeployKey)! You've successfully authenticated, but GITEE.COM does not provide shell access.

如果返回 Permission denied,请检查2.2中的 SSH 部署密钥的配置是否正确。

3.5 执行验证

手动执行部署脚本:

bash
# 自动提取 token 并验证
TOKEN=$(grep '^EXPECTED_TOKEN=' /home/ecs-user/deploy-blog.sh | cut -d'"' -f2)

bash /home/ecs-user/deploy-blog.sh $TOKEN

查看部署日志:

bash
cat /home/ecs-user/deploy.log

#只看最后几次
tail -20 /home/ecs-user/deploy.log

未完待续 点击跳转 !