📅 2026-06-12 ⏱ 2 分钟阅读

从零搭建个人博客(下)— Gitee Webhook 自动化部署

架构

写文章 → git push → Gitee → Webhook → 云服务器 → git pull → 构建 → Nginx

全链路延迟 3-5 秒。push 完刷新浏览器,新文章就在了。

最爽的部分:全程不需要打开服务器终端,不需要手动构建,不需要 FTP 上传。

先看需要什么

组件干什么用
Python 3跑构建脚本和 Webhook 接收器
Git拉取源码
Nginx反代 Webhook + 托管静态文件
systemd管理 Webhook 服务,挂了自动重启

第一步:服务器配 Gitee 访问

生成部署专用密钥:

ssh-keygen -t ed25519 -C "gitee-blog-deploy" -f ~/.ssh/id_ed25519_gitee

加到 Gitee SSH 公钥。配 SSH config:

Host gitee.com
  HostName gitee.com
  IdentityFile ~/.ssh/id_ed25519_gitee
  User git

克隆仓库:

git clone git@gitee.com:username/blog.git /opt/blog

坑: 别忘了 ssh -T git@gitee.com 先测一下连通性。装了半天发现 SSH key 没配好就尴尬了。

第二步:构建脚本

200 行 Python,核心逻辑不复杂:

#!/usr/bin/env python3
import os, markdown
from datetime import datetime

def read_posts():
    # 遍历 posts/ 解析 frontmatter + markdown
    pass

def render_index(posts):
    # 生成首页文章列表
    pass

def build():
    os.makedirs('/opt/website/posts', exist_ok=True)
    # 调用渲染函数写文件
    pass
  • 解析 markdown 的 frontmatter(标题、日期、标签)
  • 生成首页、RSS feed、Sitemap
  • 输出到 /opt/website/

第三步:部署脚本

三行搞定拉取→构建→部署:

#!/bin/bash
set -eo pipefail

git pull origin master
python3 /opt/blog/deploy/build.py
rsync -a --delete /opt/website/ /opt/nginx/html/blog/

第四步:Webhook 接收器

用 Python 内置 http.server不需要 Flask 等外部依赖

#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import subprocess, json

class WebhookHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(content_length)
        event = json.loads(body)
        
        # 只处理 master 分支的 push
        if event.get('ref') != 'refs/heads/master':
            return self._respond(200, 'Ignored')
        
        # 执行部署
        subprocess.run(['bash', '/opt/blog/deploy/deploy.sh'])

    def _respond(self, code, msg):
        self.send_response(code)
        self.end_headers()
        self.wfile.write(msg.encode())

监听 127.0.0.1:8765,不对外暴露。通过 Nginx 反代提供公网访问。

为什么用内置 http.server 不用 Flask? 少一个依赖就少一个出问题的点。部署依赖越少越好,够用就行。

第五步:systemd 保活

[Unit]
Description=Blog Webhook Receiver
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/python3 /opt/blog/deploy/webhook_receiver.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

启动:

systemctl daemon-reload
systemctl enable --now blog-webhook

Restart=always 保证进程挂了自动拉起来,不用盯着。

第六步:Nginx 反代

location /webhook/blog-deploy {
    proxy_pass http://<docker-gateway-ip>:8765;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

<docker-gateway-ip> 通常是 172.17.0.1(如果 Nginx 在 Docker 里,Webhook 在宿主机上)。

第七步:Gitee 配 Webhook

Gitee 仓库 → 管理 → WebHooks:

字段
URLhttps://your-domain.com/webhook/blog-deploy
密码可选,建议加
事件勾选 Push

测试:发一个 push,看服务器日志:

[2026-06-12 00:49:46] 🚀 开始部署
[2026-06-12 00:49:46] 📥 拉取最新代码...
[2026-06-12 00:49:46] 🔨 构建静态页面...
[2026-06-12 00:49:46] 📦 部署到 Nginx...
[2026-06-12 00:49:46] ✅ 部署成功!

最终工作流

Obsidian 写文章 → git push → 等 3 秒 → 浏览器刷新看效果

写好,push,完事。


你的博客发布流程是什么? 有没有更骚的方案?评论区聊聊。

上一篇:从零搭建个人博客(上)— Gitee + Obsidian 写作环境

🏠 首页 📝 文章 🏷️ 标签 💬 关于 🔍 搜索