最近将网站迁移到服务器上面了,想着本地更改的时候,能够将 github.io 仓库和服务器端的 git 仓库同步进行更新,尝试用 webhook 来实现我的想法

添加 SSH key 到 GitHub 仓库

登录服务器终端,输入如下命令后一直回车,直到出现例如”ssh-rsa AAAA…”

1
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

查看公钥并复制

1
cat ~/.ssh/id_rsa.pub

打开 github.io 仓库 -> Settings -> Deploy keys -> Add deploy key
Title 字段填写自己能够辨识的名称
Key 字段粘贴刚复制的内容
然后点击”Add Key”
250401.png
最后测试 SSH 连接,若成功会看到类似于 “Hi username! You’ve successfully authenticated…”这段信息

1
ssh -T git@github.com

在网站目录拉取 git

在网站目录下初始化git仓库,并拉取 github.io 仓库的内容

注:这里及后文演示的网站目录位置假设为/opt/apps/openresty/openresty/www/example.com/html

1
2
3
git init
git remote add origin git@github.com:your_username/your_username.github.io.git # 替换为你的 github.io 仓库
git pull origin gh-pages # 替换为你的实际存放分支

安装 webhook 工具

/home中创建一个临时目录 tmp

1
2
mkdir /home/tmp
cd /home/tmp

下载 webhook 的二进制文件压缩包

注:不同的操作系统的下载链接可能会不一致,详情查看https://github.com/adnanh/webhook/releases

1
wget https://github.com/adnanh/webhook/releases/download/2.8.2/webhook-linux-amd64.tar.gz

解压下载的文件

1
tar -xzf webhook-linux-amd64.tar.gz

进入解压后的目录

1
cd webhook-2.8.2-linux-amd64

将 webhook 可执行文件移动到系统 PATH 中的目录 (/usr/local/bin)

1
sudo mv webhook /usr/local/bin/

检查 webhook 是否安装成功并查看版本

1
webhook -version

清理临时目录和下载文件

1
2
cd /home/tmp
rm -rf webhook*

编写 deploy-server.sh 来拉取 github.io 仓库的文件

在适当的位置创建 deploy-server.sh 文件,这里选择的是/opt/webhook-ts

1
2
3
mkdir /opt/webhook-ts
cd /opt/webhook-ts
vim deploy-server.sh

编写 sh 文件,用于拉取 github.io 仓库的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

# 表示如果任何命令执行失败,脚本立即退出
set -e

# 打印当前工作目录
echo "当前工作目录: $(pwd)"

# 拉取最新的代码 (根据你的分支和 remote 名称调整)
echo "正在拉取最新代码..."
git config --global --add safe.directory /opt/apps/openresty/openresty/www/example.com/html
git pull origin gh-pages

echo "部署完成!"

exit 0

给予脚本执行权限

1
sudo chmod +x /opt/webhook-ts/deploy-server.sh

编写 hook.js

使用 openssl 创建 Secret 并复制

1
openssl rand -base64 32

然后打开 github.io 仓库 -> Settings -> Webhooks -> Add webhook
Payload URL 字段设置为 Webhook 接收端在互联网上的地址,这里我设置的是https://example.com/hooks/github-pull
Content type 字段选择 application/json
Secret 字段粘贴刚复制的 Secret
然后点击”Add webhook”即可
250402.png

在适当的位置创建 hook.js 文件,这里选择的是/opt/apps/openresty/openresty/www/example.com

1
2
cd /opt/apps/openresty/openresty/www/example.com
vim hook.js

编写 hook.js 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[
{
"id": "github-pull",
"execute-command": "/opt/webhook-ts/deploy-server.sh",
"command-working-directory": "/opt/apps/openresty/openresty/www/example.com/index",
"trigger-rule": {
"and": [{
"match":
{
"type": "payload-hash-sha1",
"secret": "你生成的Secret",
"parameter":{
"source": "header",
"name": "X-Hub-Signature"
}
}}]
},
"verbose": true
}
]

使用 Systemd 管理 webhook 进程

创建 Systemd Service Unit 文件

1
sudo vim /etc/systemd/system/webhook.service

编写文件内容,记得删掉注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[Unit]
Description=Webhook Listener for GitHub Deployments
After=network.target

[Service]
# 指定 webhook 可执行文件的完整路径,根据自身需要进行修改
ExecStart=/usr/local/bin/webhook \
-hooks /opt/apps/openresty/openresty/www/example.com/hook.js \
-port 12345 \
-verbose \
-ip 127.0.0.1 # 明确绑定到本地地址,提高安全性

# 自动重启策略:总是重启,除非明确停止
Restart=always

[Install]
WantedBy=multi-user.target

重载 Systemd 配置并启动 webhook 服务

1
2
sudo systemctl daemon-reload
sudo systemctl start webhook.service

检查服务状态

1
sudo systemctl status webhook.service

设置开机自启动

1
sudo systemctl enable webhook.service

设置反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
location = /hooks/github-pull {
proxy_pass http://127.0.0.1:12345; # 要对应上一步你设置的端口

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Hub-Signature $http_x_hub_signature;
proxy_set_header X-Hub-Signature-256 $http_x_hub_signature_256;
proxy_set_header X-GitHub-Event $http_x_github_event;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Content-Type $http_content_type;
proxy_pass_request_body on;
proxy_pass_request_headers on;

proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
send_timeout 60s;
}

拒绝对网站 .git 的子文件和文件夹的访问

1
2
3
location ~ /\.git {
deny all;
}

测试

进行 git push 的操作,然后打开 github.io 仓库 -> Settings -> Webhooks,再点击之前创建的 webhook,在 Recent Deliveries 查看 Response,出现如下图所示结果即代表测试成功
250403.png