【记录】自动构建 Hugo 博客至腾讯云 COS 并启用 CDN 加速

本地启动

Quick start 构建 Hugo 博客, 使用 FixIt 主题默认配置,具体样式可参考博主1博主2

初始化命令如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Init to create the directory structure
hugo new site mysite
cd mysite

# Set theme
git init
git submodule add https://github.com/hugo-fixit/FixIt.git themes/FixIt
# 修改配置`hugo.toml`
echo "theme = 'FixIt'" >> hugo.toml

# Add a new page to your site.
hugo new content posts/my-first-post.md

# 本地测试
# Start Hugo’s development server to view the site.
hugo server -D --disableFastRender

COS + CDN

  • COS(Cloud Object Storage):云对象存储,用于存储网站文件
  • CDN(Content Delivery Network):内容分发网络,可加快网页加载速度

存储桶设置

创建 bucket 设置访问权限为私有读写,在基础配置中开启静态网站。

在权限选择上,使用私有读存储桶构建的静态网站内容无法直接访问(需要公开读权限),但通过 CDN 可在回源时开启鉴权完成加速访问

CND 配置

存储桶 -> 域名与传输管理 -> 自定义 CDN 加速域名

  • 域名配置:购买域名后,完成设置,选择境外加速

国内加速需要备案(需要至少3个月的云服务器),境外加速可使用未备案的域名。

上述配置完成后,可向存储桶上传 index.html 文件,测试网页能否正常访问。

API 鉴权配置

要使用命令行工具操作 COS 和 CDN,需要获取腾讯云的 access key。

首先,点击控制台右上角的头像,进入 访问管理,切换到 用户 - 用户列表,新建用户,自定义创建,选择类型 可访问资源并接收消息,填写一个用户名,仅启用编程访问

在权限策略板块,搜索并添加 QcloudCOSDataFullControl(对象存储数据读写删除权限) 和 QcloudCDNFullAccess(内容分发网络全读写访问权限)。如果有更细粒度的权限控制要求,可以选择自定义策略,并详细控制权限和范围。

构建部署

在博客仓库根目录下新建 .github/workflows 文件夹,新建 deploy.yaml,参考博客

自动构建

 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
name: Build and deploy

# 指定触发条件
on:
  workflow_dispatch:     # 触发方式 1: 手动触发
  push:                 # 触发方式 2: push 到 master 分支时自动触发
    branches:
      - master

# 自动构建工作流
jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # 1.拉取代码仓库
      - uses: actions/checkout@v3
        with:
          submodules: true      # 下载子仓库,即主题仓库
          fetch-depth: 0
      
      # 2.准备 Hugo 环境
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'
          extended: true        # 启用 hugo extend

      # 3.构建静态页面
      - name: Build
        run: hugo --minify

目前完成了触发工作流时自动构建静态页面的配置,当工作流被触发时,便会生成静态文件放置在 public 目录下。

自动部署到 COS

将构建好的静态文件自动上传至存储桶,主要使用腾讯云官方的 cosmod 工具 来实现。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
- name: Setup Python                #配置 python 环境,cosmod 基于 python 开发
  uses: actions/setup-python@v4
  with:
    python-version: 3.9

- name: Setup coscmd               # 安装 coscmd 工具
  run: sudo pip install coscmd

- name: Configure coscmd           # 配置存储桶参数和鉴权
  env:
    SECRET_ID: ${{ secrets.SecretId }}      # SecretId
    SECRET_KEY: ${{ secrets.SecretKey }}    # SecretKey
    BUCKET: ${{ secrets.Bucket }}           # 存储桶名称,在存储桶基本信息中获取
    REGION: ${{ secrets.Region }}           # 存储桶地域,在存储桶基本信息中获取,如 ap-shanghai
  run: coscmd config -a $SECRET_ID -s $SECRET_KEY -b $BUCKET -r $REGION # 为 coscmd 工具配置存储桶信息

- name: Upload to COS
  run: coscmd upload -rfs --delete public/ /    # 上传 public 中的文件 至 cos 存储桶根目录
                                                # -r 参数用于上传文件夹;
                                                # -s 参数用于同步上传,即仅上传发生变化的文件;
                                                # -f 参数用于强制同步文件;
                                                # --delete 参数用于删除云端中本地已经删除的文件

在 Github 仓库中配置{{ secrets.xxxxxx }},不能将鉴权信息泄露。

在仓库的 Settings 界面,选择 Secrets - Actions,点击 New repository secret,分别配置 SecretId SecretKey BucketRegion

CDN 刷新函数

使用腾讯云的 Python-SDK ,在部署完成后执行脚本调用 API 完成缓存刷新。

缓存刷新脚本

在仓库根目录下创建文件 flush-dns.py,将其中的 https://blog.example.com/ 修改为 CDN 加速域名。

 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
import json
import argparse
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import (
    TencentCloudSDKException,
)
from tencentcloud.cdn.v20180606 import cdn_client, models

# 传入参数
parser = argparse.ArgumentParser(description='-i <secretId> -k <secretKey>')
parser.add_argument('-i', '--secretid', type=str, required=True, help='secretId')
parser.add_argument('-k', '--secretkey', type=str, required=True, help='secretKey')
args = parser.parse_args()

try:
    cred = credential.Credential(args.secretid,args.secretkey)
    httpProfile = HttpProfile()
    httpProfile.endpoint = "cdn.tencentcloudapi.com"

    clientProfile = ClientProfile()
    clientProfile.httpProfile = httpProfile
    client = cdn_client.CdnClient(cred, "", clientProfile)

    req = models.PurgePathCacheRequest()
    params = {"Paths": ["https://blog.example.com/"], "FlushType": "flush"}
    req.from_json_string(json.dumps(params))

    resp = client.PurgePathCache(req)
    print(resp.to_json_string())

except TencentCloudSDKException as err:
    print(err)

配置工作流

1
2
3
4
5
6
7
- name: Flush CDN
  env:
    SECRET_ID: ${{ secrets.SecretId }}      # 传入鉴权信息
    SECRET_KEY: ${{ secrets.SecretKey }}
  run: |                                    # 安装 sdk 并运行刷新脚本
    pip install --upgrade tencentcloud-sdk-python
    python flush-dns.py -i $SECRET_ID -k $SECRET_KEY

Reference

0%