GitHub Actions 自动部署 Hexo 博客到 cPanel 虚拟主机
本文最后更新于:2022年4月8日 凌晨
1 引言
我在网上看到很多用 GitHub Actions 自动部署 Hexo 博客的文章。
因为我有多台设备,不想重复在每一台设备上配置 Hexo+Git 的环境,而是想直接把 MarkDown 文件推送到 GitHub,所以存在自动部署的需求,于是尝试着自动部署自己的博客。
但是因为我是新手上路,而且我的博客主力镜像是在虚拟主机上,所以掉了不少坑。
下文将过程和坑简单叙述一下。
2 操作步骤
2.1 博客结构与虚拟主机
我有两个 GitHub 仓库:
kukmoon_blog
:私密仓库,存放博客源码;kukmoon.github.io
: 公开仓库,存放静态博客页面。
此外,我把博客主力镜像放在虚拟主机上,它使用 cPanel 管理面板,支持 Git。
也就是说,我要实现的自动部署是,一次推送,同时部署到 kukmoon.github.io
仓库和我的虚拟主机。
kukmoon_blog
仓库已经与本地的 C:\Users\Kukmoon\kukmoon_blog
仓库建立了关联。
注意:单仓库双分支的情况,不适用于本文,可参考这篇文章[3]。
2.2 密钥配置
2.2.1 生成部署密钥
执行下列命令,在本地生成一对新的公钥和私钥,专门用于 GitHub Actions 自动部署。不使用本机已有的公钥和私钥,是为了避免本机私钥泄漏。
ssh-keygen -f github-deploy-key -C "kukmoon.github.io"
2.2.2 为 GitHub 配置部署密钥
按照参考文献[1]的介绍,将私钥 github-deploy-key
的文件内容添加到 kukmoon_blog
仓库的 Settings → Secrets → Add a new secret
页面上,Name
为 HEXO_DEPLOY_PRI
(后面的代码要用到这个名称);
再将公钥 github-deploy-key.pub
的文件内容添加到 kukmoon.github.io
仓库的 Settings → Deploy keys → Add deploy key
页面上,Title
为 HEXO_DEPLOY_PUB
,勾选 Allow write access
选项。
2.2.3 为虚拟主机配置部署密钥
按照参考文献[4]的介绍,通过 cPanel 面板,将公钥 github-deploy-key.pub
的文件内容导入,并且授权(Authorize)即可。注意:只导入公钥,千万不要导入私钥!
类似地,如果要通过 GitHub Actions 把 Hexo 博客自动部署到 VPS,也要将公钥 github-deploy-key.pub
的文件内容导入到 VPS 中。
2.3 编写 Workflow
最好是在本地编写 Workflow,然后推送到 GitHub 的 kukmoon_blog
仓库。在本地编写比较方便,而且首次推送时就会执行这个 Workflow。
按照参考文献[1]的介绍,在 C:\Users\Kukmoon\kukmoon_blog
下创建 .github/workflows/deploy.yml
文件。
在这个文件中粘贴以下内容,并保存。
name: CI
# 只监听 master 分支的改动
on:
push:
branches:
- master
# 自定义环境变量
env:
GIT_USER: Kukmoon # 改成你自己的 GitHub 用户名
GIT_EMAIL: kukmoon97@gmail.com # 改成你自己的 GitHub 注册邮箱
jobs:
build:
name: Build on node ${{ matrix.node_version }} and ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest]
node_version: [12.x] # 改成你本地的 Node.js 版本,可以用 `node --version` 命令查询
steps:
# 获取博客源码和主题,我的主题放在 `theme` 文件夹中,可随博客源码一起获取
- name: Checkout
uses: actions/checkout@v2
# 用 Node.js 渲染
- name: Use Node.js ${{ matrix.node_version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node_version }}
# 安装 Hexo-cli
- name: Install hexo with dependencies
run: |
npm install -g hexo-cli
# 安装依赖
- name: Install hexo with dependencies
run: |
npm install
# 配置环境
# ssh-kenscan github.com >> ~/.ssh/known_hosts # 从 GitHub 获取公钥并保存到 known_hosts 文件
# ssh-keyscan 999.999.999.999 >> ~/.ssh/known_hosts # 从我的虚拟主机(假设IP为999.999.999.999)获取公钥保存到 known_hosts 文件
- name: Configuration environment
env:
HEXO_DEPLOY_PRI: ${{secrets.HEXO_DEPLOY_PRI}}
run: |
sudo timedatectl set-timezone "Asia/Shanghai"
mkdir -p ~/.ssh/
echo "$HEXO_DEPLOY_PRI" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts
ssh-keyscan 999.999.999.999 >> ~/.ssh/known_hosts
git config --global user.name $GIT_USER
git config --global user.email $GIT_EMAIL
# 生成并部署
- name: Deploy hexo
run: |
hexo clean
hexo g -d
# 部署后更新博客源码,用于添加 abbrlink,如果不用 abbrlink,需要删除
- name: Update Blog
run: |
sh "${GITHUB_WORKSPACE}/.github/script/blog-update.sh"
2.4 abbrlink(短链接)
我用了 Hexo 插件 hexo-abbrlink
,来为博文生成短链接,为了将短链接写入 MarkDown 文章的 Front-matter
区域的 abbrlink
字段,需要在 hexo g
之后运行一个脚本 blog-update.sh
,将 Hexo 对 MarkDown 文章的修改推送回 kukmoon_blog
仓库[2][5]。
按照参考文献[2]的介绍,在 C:\Users\Kukmoon\kukmoon_blog
下创建 .github/script/blog-update.sh
文件,复制粘贴以下内容,保存。
#!/bin/sh
if [ -z "$(git status --porcelain)" ]; then
echo "nothing to update."
else
git add .
git commit -m "triggle by commit ${GITHUB_SHA}" -a
git push origin master
fi
2.5 推送
用 hexo new
新建一篇博客文章,保存。
接下来,添加、提交、推送。
git add .
git commit -m "测试自动部署-1"
git push
GitHub 的 kukmoon_blog
仓库就开始执行 Workflow 文件中的指令,进行自动部署。如果成功,就会出现绿色对勾。
2.6 拉取
等博客的静态页面更新后,最好在博客源码所在的本地仓库( C:\Users\Kukmoon\kukmoon_blog
文件夹) 执行一次 git pull
命令,把 Hexo 的 abbrlink 插件对最新的 MarkDown 文章的修改拉取到本地。
当然,等下次推送时再拉取也可以,但是,如果在拉取之前对最新的 MarkDown 文章进行了修改,就会与远程的同名文件产生冲突,导致拉取失败。所以,还是及时拉取比较好。
3 错误分析(我掉过的坑)
参考文献[2]列出了作者遇到的四个错误。下文列出我遇到的错误(我掉过的坑)。
3.1 提示缺少 db.json 文件
远程渲染时,提示缺少 node_modules/mine_db/db.json
文件。
打开 C:\Users\Kukmoon\kukmoon_blog\.gitignore
文件,看看 db.json
是不是在里面,把它改成 /db.json
。
文件 .gitignore
是排除列表,不会被 Git 提交到分支,也不会上传到 GitHub 的远程仓库。/db.json
表示只排除本地仓库根目录下的 db.json
文件,不会排除子目录中的同名文件[8]。
3.2 Host key verification failed
把静态页面部署到虚拟主机时,提示 Host key verification failed
。
这个坑让我花了很多时间,谁让我是前端小白呢?
SSH 远程登录需要验证密钥。如果让 A 机通过 SSH 连接 B 机,A 机事先没有在 ~/.ssh/known_hosts
文件中保存 B 机发来的公钥(或者公钥不匹配),就会出现此错误[6]。我只需要把虚拟主机的 IP 地址和公钥添加到这个文件中就可以了。上述 Workflow 中的 ssh-keyscan 999.999.999.999 >> ~/.ssh/known_hosts
一行就是起到这个作用(请把此处的 999.999.999.999
改成你的虚拟主机或 VPS 的 IP 地址)。
4 讨论
4.1 GitHub Actions 的运行原理
GitHub Actions 是在虚拟主机中运行的。GitHub 按照 on
节中的要求监听事件的发生,一旦事件发生,就按照 job
中的要求指定虚拟主机的操作系统,在虚拟主机中设定 env
节中的环境变量,之后执行 steps
节中的命令。它可以在虚拟主机中运行 Linux 命令、安装应用程序、运行应用程序、运行 GitHub Actions 脚本、运行某个仓库中的代码,等等。例如,checkout
表示将某个仓库中的内容读取到虚拟主机。全部命令运行结束后,清空虚拟主机,退出。
这就是需要选择运行环境为 Ubuntu、安装 Node.js 与 Hexo、设置环境变量、运行 name: Configuration environment
节中的一连串指令的原因。
这也是需要把 Hexo 对博客源码的修改用 git push 推送回去的原因。
4.2 检测依赖是否完整
Hexo 博客所需要的绝大多数依赖都放在 C:\Users\Kukmoon\kukmoon_blog\node_modules
中。如果有些依赖没有安装在这里,但是又是静态 HTML 文件渲染所必需的,就需要修改 Workflows 文件,在 name: Install hexo with dependencies
一节中单独安装它。
参考文献[2]提到使用 MathJax 时需要单独安装 pandoc
,还好我用 KaTeX 渲染数学公式,远离 MathJax 保平安!
4.3 用 git push 代替 Hexo 部署
Hexo 把静态页面部署到 GitHub Pages,本质上是调用 git push
命令,因此,我们可以在 Workflow 中,只执行 hexo g
命令,生成静态页面,然后用 git push
命令推送到 GitHub、Coding、Gitee,或者支持 Git 的虚拟主机,详见这篇文章[7]。
5 结论
用 GitHub Actions 完全可以实现自动部署 Hexo 博客到 GitHub 和 虚拟主机。在 GitHub 上建立两个仓库,一个存放博客源码,一个存放生成的静态页面(GitHub Pages)。为博客源码仓库编写 Workflow,可以实现每当把修改推送到博客源码仓库时,就可以自动渲染生成静态页面,并部署到 GitHub Pages 仓库,也可以部署到虚拟主机,不需要本地具备 Node.js+Hexo 的环境,只需要有 Git 即可。
6 参考文献
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!