前言
本博客从前都是在我的本地电脑上编辑并构建,再通过SFTP等程序上传到服务器目录,这整个流程都需要手动操作且十分繁琐耗时
最近 Stack主题 更新到 v4 版本, 就想着把这些问题优化一下,并使用更加规范的方式管理项目
Stack主题提供了官方入门模板 Starter template 可以快速创建一个实例并部署至 Github Pages
本文所述的方法适用于从Stack主题源代码构建并使用Github Action推送至私有服务器,不使用Github Pages的读者,部分内容参考 Stack - 为博客设计的卡片式主题 ,请优先阅读 Stack主题官方文档
起步
1.让我们从零开始 - 环境搭建
本博客早期发布过一篇在本地电脑搭建Stack静态博客的文章,其中很多操作不符合规范且导致后续维护面临很多麻烦,因此在这里我们从头开始,创建一个新的项目
在开发环境中安装 Hugo,在使用 Stack v4主题时,必须确保 Hugo 的版本 ≥ v0.157.0 且使用 extended version
确定你的开发目录,按照读者喜欢的方式,使用hugo new site <项目名称> 来创建一个项目文件夹,并创建一个私有的Github存储库,将此项目的文件托管于Github中
使用以下命令将 Stack主题 以一个 submodule 的形式添加到项目中。至此一个最简单的开发环境就搭建完成了
1
2
| # 如果您已经为站点使用了 Git,可以运行以下命令将主题添加为子模块:
git submodule add https://github.com/CaiJimmy/hugo-theme-stack/ themes/hugo-theme-stack
|
2.修改主题并丰富你的博客
注意:任何情况下都不要直接修改 themes/hugo-theme-stack 下的任何文件
如果您通过 Git / Git 子模块安装了主题,您可以直接修改主题文件并在本地站点中查看更改。
但是,您不能直接提交并推送更改,因为您没有推送到主题存储库的权限。
如果读者通过 fork 的方式存储自己的主题文件,那就可以直接修改主题文件,不过可能影响未来拉取更新
将你需要修改的一切文件都按照 themes/hugo-theme-stack 下相同的文件路径复制到项目根目录中,比如需要修改themes/hugo-theme-stack/layouts/404.html 这个文件,就将其复制到项目目录/layouts/404.html ,对此文件进行修改即可,Hugo在构建时会优先查找项目目录
在 Stack v4版本中,移除了一些原有的规范并引入了新的功能,读者可以根据新的规范,调整自己的文章内容、布局。具体变更详见 升级到 v4 | Stack
完成你所需的所有修改后,使用Github Desktop或者命令行工具,将你的项目文件全部推送至Github存储库中,后续的新文章,主题修改、更新等操作都只需要将更改的文件推送至存储库即可,且submodule的形式能够确保每次构建都使用Stack主题的最新版本

3.创建 Github Action 工作流
在Github网站中选择博客存储库对应的 Actions -> New workflow 搜索 Hugo 并Configure,此时会在项目中创建一个名为hugo.yml的文件,向其中写入以下内容
此示例只基于 Stack v4主题测试,早期版本或其他版本未经测试,请读者自行尝试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
| name: Deploy Hugo site
on:
push:
branches: ["main"]
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
defaults:
run:
shell: bash
jobs:
# Build job
build:
runs-on: ubuntu-latest
env:
#截至发文 Hugo 的最新版本,最低≥0.157.0
HUGO_VERSION: 0.158.0
steps:
- name: Install Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: Install Dart Sass
run: sudo snap install dart-sass
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Node.js dependencies
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: Build with Hugo
env:
HUGO_CACHEDIR: ${{ runner.temp }}/hugo_cache
HUGO_ENVIRONMENT: production
#注意修改域名
run: |
hugo \
--minify \
--baseURL "https://yourdomain.com/"
#以下内容注意按照自己的服务器实际情况更改,花括号内的是环境变量,默认不用更改
- name: Deploy to VPS via SSH
uses: easingthemes/ssh-deploy@main
env:
SOURCE: "public/"
REMOTE_HOST: ${{ secrets.SERVER_IP }}
REMOTE_USER: ${{ secrets.SERVER_USER }}
REMOTE_PORT: ${{ secrets.SERVER_PORT }}
SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
TARGET: "/var/www/html/"
ARGS: "-avz --delete"
|
保存这个文件后 Github Action 将立即开始执行一次构建,因为暂时还没有配置所需的环境变量,所以会在 Deploy 这一步卡住并报错,不用理会
前往 项目库 -> Settings -> Secrets and variables -> Actions -> New repository secret,分别创建4个名为SERVER_IP SERVER_USER SERVER_PORT SERVER_SSH_KEY ,并填入自己的私有服务器的信息,此类信息将保存在你的Github账户中且不会被二次展示,保护好自己的账户
一切就绪后可在Actions一栏中再次运行工作流,构建成功

此时,构建的网页文件也一站式推送到了服务器上,Nginx可以直接读取它们了
4.进阶设置
1.在服务器上创建一个专属于 Github Action 操纵的账户
此举可避免直接给予Github虚拟机root权限所带来的安全隐患,在私有服务器上执行以下命令即可,此处以 Ubuntu 24.04 系统并使用 Nginx 网关为例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| sudo adduser github-deploy
sudo usermod -aG www-data github-deploy
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 775 /var/www/html
sudo chmod g+s /var/www/html
sudo su - github-deploy
ssh-keygen -t ed25519 -C "github-action-deploy"
mkdir -p ~/.ssh
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
#显示私钥
cat ~/.ssh/id_ed25519
|
此时将前文为Actions配置的环境变量修改为新的用户和新的SSH私钥即可实现最小权限设计原则
2.自动清理CDN缓存
一般静态博客站点都使用CDN服务来加快访问速度,但此举可能导致网站更新了但访问者依旧处于缓存期的情况,此时可以通过 Actions在每次构建成功后调用CDN服务商提供的API来清理指定域名的缓存实现网站更新后实时刷新,这里以 Cloudflare CDN 为例,在工作流中新增一个job,注意调整 yaml 的缩进规范
1
2
3
4
5
6
7
8
9
10
11
12
13
| runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Purge cache
uses: jakejarvis/cloudflare-purge-action@master
if: success() # 仅在之前步骤成功时执行
env:
CLOUDFLARE_ZONE: ${{ secrets.CLOUDFLARE_ZONE_ID }}
CLOUDFLARE_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# 指定具体的 URL,支持多个,用逗号分隔
CLOUDFLARE_URL: ${{ secrets.CLOUDFLARE_URL }}
|
按照内容所示的变量设置好对应自己Cloudflare账户的令牌即可
结语
这次优化使整体项目结构更加规范且易于管理维护,把很多操作自动化,可以将更多的精力放在对文章内容的打磨上
版权
本文章隶属于 DDverse ,遵循 © CC BY-NC-SA 4.0 协议,如需转载请保留来源并在必要的时候告知我