说是自动化博客部署,其实是记录了下 枋柚梓的猫会发光 的部署过程,基本概括来说就是通过 Github Action 处理代码的提交,部署博客到 Github、Gitea、COS 中,此外还包含一些 GPG 的签名提交、自托管主机遇到的一些坑和一些其它功能的使用过程。
如你所见,这个部署流程是繁杂的,如果只是将 Hexo 博客部署到 Github、COS、CVM 等,其实都有对应现成的轮子可以用。不过出于个人定制的缘故,我将源码发送到了多个位置:整站内容部署到服务器、Github 仓库;静态文件(js,css,fonts)单独同步到另一个 Github 仓库,并且使用 Jsdelivr 加速访问静态库;而图片类文件则同步到腾讯云对象存储,以方便使用它的图片处理功能(自适应 Webp 自适应、Guetzli 自适应等)。
同时,强迫症心理作祟 ,各个环节都用上了 GPG 签名;再同时还是强迫症的缘故,网站的域名解析几乎不对境外开放(只有 inkss 的域名做了全球解析),所以又用上了 Github Actions 的自托管主机;再然后还自建了 Gitea 的代管托管站,又将整站同步一份到 Gitea 里。
本文包括但不限于以下内容:
- SSH 私钥提交
- GPG 部署与代码签名
- Github Action 基本语法规则
- Github Action 自托管主机使用
- Gitea 的 Webhook 及本地代码同步
- 利用 Gulp 批量替换静态资源访问地址
- 腾讯云 COS 部署及 CDN 缓存刷新
一、SSH & GPG
使用 SSH 连接到 Github
这部分是基础的基础,不作详细解释,大致的流程就是:生成密钥,然后将公钥上传到 Github,完了齐活儿~ 可以参考此链接操作:使用 SSH 连接到 Github 。
使用 GPG 对提交进行签名
简要介绍一下 GPG :
至于为什么要使用 GPG 可以这样理解,由于 Git 的身份认证只需要配置用户名和邮箱,且这俩可以任意修改,甚至 Git 的 commit 都可以批量修改,那么有人伪造提交记录,Github 也是无法分别的。所以需要一个我证明是我自己的过程,也就是利用 GPG 对一次提交记录进行签名,Github 利用你上传的公钥对签名解密,验证通过后就可以相信对应的提交记录是你真实发出的。
总结就是 SSH 用来验证身份,GPG 用来验证 “著作权” 。
GPG 的安装
对于类 Uinux 用户,系统已经默认安装了 GPG ,直接使用即可;Windows 用户可以下载 GPG 的 命令行工具 ,当然最简单的还是利用 Scoop 安装:
Windows 安装 scoop
scoop install gpg |
GPG 的使用
安装完成之后就是生成 GPG 密钥对,生成过程参考此链接操作:生成新 GPG 密钥 。
GPG 的导入导出
如果已有 GPG 密钥是可以直接导入,这点比 SSH 密钥的导入导出方便很多,下面是查看系统中已有的密钥和对其导入导出的命令:
列出您拥有其公钥和私钥
➜ ~ gpg --list-secret-keys --keyid-format=long |
其中,ses 和 pub 后跟的字符串为对应 ID,例如本例中 GPG 密钥 ID 为 705CF548160B570E
。
导出私钥和公钥
➜ ~ gpg -a -o gpg-public.key --export 705CF548160B570E |
相应的导入密钥命令如下,同样导入私钥时需要输入密码。
导入公钥和私钥
➜ ~ gpg --import gpg-public.key |
GPG 的 Git 调用
当密钥导入到系统后,需要配置 Git 命令调用 GPG 签名:
配置密钥并开启全局签名验证
➜ ~ git config --global user.signingkey 705CF548160B570E |
添加 GPG 公钥至 Github
我们需要将公钥上传到 Github,以方便其对签名信息解密,可以参考此链接操作:新增 GPG 密钥到 GitHub 帐户。
二、Github Action
如上图所示我将部署流程拆分成了三部分:分发、同步和备份,分发和同步通过 Ubuntu-last 执行,备份通过自托管主机执行,下面根据各个要点逐一展开。
部署博客 - CVM
部署博客源码到服务器
这一流程的主要目的是将生成的网站源码部署到服务器的网站目录中,这里呢其实最简单的就是直接利用 SSH 将文件发送到服务器,涉及的插件是:ssh-deploy,基本的 Action 命令可以这样写:
ssh-deploy 的使用
- name: Deploy to Server |
复杂点就是先将网站源码部署到 Github 仓库,然后利用 WebHook 触发服务器,服务器再执行克隆命令,从代码仓库中拉取最新内容,服务器端执行的克隆命令大致如下:
宝塔 Webhook 命令
|
部署博客源码到托管仓库
由于我自建了 Gitea 代码托管,秉承着不能浪费的原则:不如将一份博客源码同步到 Gitea 仓库 ,然后顺带还可以同步进 Github 仓库,这里用到的工具是 hexo-deployer-git,基本的 Action 命令可以这样写:
部署博客到 Git 仓库
# Deployment 部署 |
Github Action 自托管主机
但是,由于心理洁癖的缘故,除了 inkss.cn
的域名,其它的几个域名没有对境外解析,换句话就是执行 Github Action 的服务器联系不到我的 Gitea 网站,我又修改不了它的 hosts
文件,所以一不做二不休,整自托管主机。关于将自托管主机的部署可以查看这篇文档:添加自托管的运行器,如此在配置文件中,运行环境就需要更改成自己的主机:runs-on: self-hosted
。
接下来就是踩坑的血泪史了,自托管主机不像 Github 主机那样,每次运行都是新环境,需要特别留意环境的问题。假设你按照安装流程并且没有修改路径的话,那么它的运行路径为:
基础运行地址
~/actions-runner/_work/Hexo-Blog/Hexo-Blog/ |
每一次执行 Action 时,这个目录中除了 .github\workflows
外其余内容都会被清空;然后是环境变量,在安装 Github Action 的时候是不允许 root
或者 sudo
下执行命令的,所以原则上你 Action 的环境变量应该是当前用户的环境变量,可是离谱的事情发生了:在终端打印 $HOME
时,读出的内容是 /root/
,而 $PATH
只有系统的环境变量。
这简直是坑惨了人,明明 whoami
和 pwd
得到的都是普通用户下的路径和名称,但是这些变量就是不对,最明显的便是 Node
环境找不到,一个劲儿的去往 root 的目录读, 然后没有权限不停的报错。 这一点我是花了很长时间才发现,尤其是 HOME 指向 root 这一点,离谱!
解决方案就是重写环境变量:
为 Job 配置公共环境变量
jobs: |
部署博客 - COS
部署到对象存储就和我的域名没有关系了,此部分可以使用 Github 的主机,由于将部署到 CVM 和 COS 拆分成两个流程,那么配置文件自然要独立成两个,我在 Hexo 文档中看到关于多个配置文件整个使用的:
Hexo 多配置文件
hexo generate --config custom.yml,custom2.json |
但是实际体验中发现似乎这部署时并没有将 _config.yml
和 _custom.yml
合并成一个,维护两个配置文件自然不显示,最终采用了将主配置文件中不保存 deploy
段,将其只放进子配置文件中,部署时在 Action 里用 >>
整合下使用。
部署博客 - 同步文件
其实这部分没什么好说的,就是克隆仓库,然后将最新的内容复制到仓库中,最后执行提交。
Workflows 文件
总的 Workflows 文件可以在这个链接处查看:Hexo-Blog/.github/workflows/main.yml
三、附录内容
GPG 的免密校验
在使用 GPG 对 Git 提交签名的过程中,每次都需要输入主密码对私钥进行认证,这类交互式程序个人使用还好,但是在 Action 这种无人值守的自动程序中就面临凉凉的问题了,我检索了一部分资料实在没找到如何在 Git 提交的过程中自动完成密钥验证。不过倒是找到了免密解密文件,由于密码有一定的缓存时间,那么在正式的 Git 提交前我只需要进行一次解密操作,后续一段时间内都无需输入密码,四舍五入下也算完成了免密提交。
大致流程是这样:首先就是利用公钥加密一份文件,然后在执行类似 Git 提交的操作前对加密后的文件进行一次解密,刷新密码的缓存时间。
利用 GPG 私钥解密公钥解密的文件
gpg -d --pinentry-mode=loopback --passphrase-file PASSWD ~/gpg/szyink.gpg |
更新:可以通过 crazy-max/ghaction-import-gpg@v3
完成 GPG 密钥的部署及密码缓存。
是否要将 GPG 公钥提交
在一些博客教程中,都提到过将 GPG 公钥上传到公钥服务器中,但是我在读到 2021年,用更现代的方法使用PGP(下) 中的 安全风险和争议, 被玩坏的 KeyServer 后,忽然就意识到我完全没有将公钥发布出去的需求,它提供的加密功能又不会在生活中用到,最多最多只是用在 Github 之类的验证上,但是上传到公钥服务器就意味着永远无法删除,这不太好 。
Github Action 的运行目录
对于 Github 的主机来说,项目的运行目录位于(起码 Ubuntu 主机是这样),而自托管主机就需要看个人配置了,直接登陆到服务器查看它不更香嘛。
Git 主机的基础仓库路径
~/work/project-name/project-name/ |
Gulp 替换静态资源链接
我的对象存储的访问域名是 static.inkss.cn
,在博文源码中关于图片的引用是利用 Typecho 按照相对路径导入的,形如:../../imgs/article/自动化博客部署/Hexo博客自动化部署.sv
,所以如果需要将访问地址修改为静态站的,那就得批量修改类似的链接,这里采用了 Gulp 操作。
Gulp 除了能压缩文件外,还可以替换文本
gulp.src(['./public/**/*.html','!./public/{lib,lib/**}']) |
统一 Commit message
在 Github Action 中,可以利用 ${{ github.event.head_commit.message }}
获取到触发本此流程的 message
信息,所以在提交时使用这个变量就达到替换的目的了,在类似于命令行中可以直接使用该变量:
获取原始提交信息
git commit -m '自动化部署:${{ github.event.head_commit.message }}' |
但是对于 hexo-deployer-git
来说,它的提交信息是配置在 yml
文件中的,可以借助 microsoft/variable-substitution
完成变量的替换,同样的操作还可以替换配置文件中的隐私变量:
利用 secrets 存储重要信息
- name: '填充密钥' |
Github Action 的守护进程
利用宝塔面板的 Supervisord 直接创建即可,也就是:
- command=/home/szyink/actions-runner/run.sh
- directory=/home/szyink/actions-runner/
- user=szyink