前言

本教程将详细说明如何通过Github Pages + Hugo + Cloudflare从零到一构建一个免费的静态博客站,让你在网络中拥有自己的一亩三分地。

基本原理

  • Hugo是Go语言实现的静态页面生成工具,用于将.md格式的文档源文件转换为浏览器可以渲染的.html文件。
  • Github Pages托管.html文章,可以通过username.github.io访问博客。
  • Cloudflare用于提供反向代理,完成自定义域名到username.github.io的映射,从而隐藏github io域名。此外也提供免费的HTTPS证书和HTTP重定向服务,保证安全访问。

准备

  1. 准备2个Github空仓库,一个设置为Public,一个设置为Private。其中公开的仓库用于存储静态页面,私有仓库用于存储外部不可见的源文件。公开的仓库命名必须为username.github.io,其中username是你的Github用户名。
  2. 这一条不是必须的。如果你想自定义域名,可以去域名商平台挑选购买自己喜欢的域名,作者本人是在Spaceship选购的域名,年费不超过10元,很便宜。
  3. 下载并安装Hugo,可以参考Hugo官方的安装教程

搭建步骤

1. 创建新的Hugo站点

# --format yaml指定hugo的配置文件格式为yaml
hugo new site /Path/to/hugo-project --format yaml

# 初始化hugo项目仓库
cd /Path/to/hugo-project
git init

2. 安装主题

# 安装PaperMod主题,你可以替换为自己喜欢的hugo主题
git submodule add --depth=1 https://github.com/adityatelange/hugo-PaperMod.git themes/PaperMod
git submodule update --init --recursive # needed when you reclone your repo (submodules may not get cloned automatically)

3. 编辑配置文件hugo.yaml

baseURL: https://username.github.io/
languageCode: en-us
title: My Blog
theme: PaperMod

# 基础设置
enableGitInfo: false
enableEmoji: true # 支持 emoji 显示
paginate: 10 # 一页显示10篇文章

# params底下的应该是PaperMod的设置
params:
  homeInfoParams:
    Title: "👋 Welcome to My Blog"
    Content: "Hi, this is my blog."
  
  socialIcons:
    - name: "rss"
      url: "/index.xml"
    - name: "email"
      url: "[email protected]"
    - name: "github"
      url: "https://github.com/username"


  label:
    text: "User's Blog"
    icon: /favicon.ico  # 导航栏显示的图标
    iconHeight: 35  # 控制导航栏图标大小

  assets:
    disableHLJS: true
    favicon: "/favicon.ico"
    favicon16x16: "/favicon-16x16.png"
    favicon32x32: "/favicon-32x32.png"
    # apple_touch_icon: "/apple-touch-icon.png"
    # android_chrome_192: "/android-chrome-192x192.png"
    # android_chrome_512: "/android-chrome-512x512.png"

  env: production
  defaultTheme: auto
  disableSpecial1stPost: true
  ShowRssButtonInSectionTermList: true
  ShowToc: true
  # 文章设置
  ShowReadingTime: false # 显示阅读时间
  ShowPostNavLinks: true
  ShowBreadCrumbs: true
  ShowCodeCopyButtons: true
  ShowWordCount: true # 显示字数统计
  ShowAuthor: true # 显示作者

menu:
  main:
    - name: Posts
      url: /posts/
      weight: 1
    - name: Archive
      url: /archive/
      weight: 2
    - name: Search
      url: /search/
      weight: 3
    - name: Tags
      url: /tags/
      weight: 4

# 输出设置
outputs:
  home:
    - HTML
    - RSS
    - JSON # 用于搜索功能
  section:
    - HTML


# 文章页面设置
permalinks:
  posts: /posts/:year-:month-:day-:filename/

# Markdown 渲染设置
markup:
  goldmark:
    renderer:
      unsafe: true

4. 配置Search和Archieve功能

Search功能,创建content/search.md:

---
title: "Search"
layout: "search"
---

Archieve功能,创建content/archieve.md:

---
title: "Archive"
layout: "archives"
url: "/archive/"
summary: archives
---

5. 自定义icon

icon就是浏览器打开网页时标签上显示的小logo,你可以选择心仪的图片去favicon生成下载。下载后将icons解压到static/下。

6. 创建第一篇文章

hugo new posts/1st/index.md,hugo会在content/hugo/1st/index.md中生成titledatedraft等字段。

打开该文件并编辑,例如:

---
date: '2024-12-16T16:19:36+08:00'
draft: false
title: 'hello, world'
tags: ["test"]
---
这是我的第一篇博文

本地构建预览:hugo server,随后根据提示在浏览器中预览生成的博客页面。

7. 配置自动部署

hugo-project/创建.github/workflows/deploy.yaml:

name: Deploy Hugo site to Pages

on:
  push:
    branches:
      - main
  workflow_dispatch:  # 允许手动触发

# 设置并发部署策略
concurrency:
  group: "pages"
  cancel-in-progress: false

# 默认使用 bash
defaults:
  run:
    shell: bash

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.138.0  # 指定 Hugo 版本
    
    steps:
      # 安装 Hugo
      - 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          

      # 安装 Dart Sass(如果需要)
      - name: Install Dart Sass
        run: sudo snap install dart-sass
      
      # 检出代码
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: recursive  # 获取子模块
          fetch-depth: 0        # 获取完整的 git 历史

      # 安装 Node.js 依赖(如果需要)
      - name: Install Node.js dependencies
        run: |
          if [[ -f package-lock.json || -f npm-shrinkwrap.json ]]; then
            npm ci
          fi          

      # 构建 Hugo 站点
      - name: Build with Hugo
        env:
          HUGO_ENVIRONMENT: production
          TZ: Asia/Shanghai  # 设置时区
        run: |
          hugo \
            --gc \
            --minify \
            --baseURL "https://username.github.io/"  # 替换为你的 URL          

      # 部署到外部仓库
      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
          external_repository: username/username.github.io  # 替换为你的外部仓库
          publish_branch: main
          publish_dir: ./public
          #cname: your-custom-domain.com  # 添加这一行,替换为你的域名,避免每次deploy后都要手动更新CNAME文件
          commit_message: ${{ github.event.head_commit.message }}
          user_name: 'github-actions[bot]'
          user_email: 'github-actions[bot]@users.noreply.github.com'

8. 设置仓库密钥对

1. 生成SSH密钥对

# 生成密钥对blog_repo 和 blog_repo.pub
# .pub是公钥,另一个是私钥
ssh-keygen -t rsa -b 4096 -f blog_repo

2. 私有仓库添加私钥

  • 打开私有仓库的Settings
  • 点击左侧Secret and variables -> Actions
  • 点击New repo secret
  • Name字段填写:ACTIONS_DEPLOY_KEY
  • Secret字段填写私钥全部内容
  • 点击Add secret

3. 公开仓库添加公钥:

  • 打开公开仓库的Settings
  • 点击左侧的Deploy keys
  • 点击Add deploy key
  • Title字段填写:HUGO_DEPLOY_KEY
  • Key字段填写公钥全部内容
  • 点击勾选Allow write access
  • 点击Add key

通过以上设置,每当有更新操作提交到私有仓库,私有仓库通过Gitub Actions自动生成新的静态页面,再自动同步到公开仓库,从而实现自动部署和隐私保护。

9. 推送源文件到私有仓库

git add .
git commit -m "Initialize repo"
git branch -M main
# 添加远程私有仓库
git remote add origin [email protected]:username/private-repo-name.git
git push -u origin main

10. 等待自动部署完成

等待一分钟左右,即可通过username.github.io访问博客。
如果长时间无法访问,可以点击仓库的Actions查看执行结果,如果是红色则根据报错原因排查解决。
至此,我们初步完成了搭建。如果你不满足于通过github io访问自己的博客,我会在下一篇文章继续讲解Cloudflare的配置。

后期维护

1. 编写文章

hugo new posts/new-post-name/index.md

2. 本地预览

hugo server

3. 脚本推送

  • 新建auto-push.sh:
#!/bin/bash
# 检查是否提供了参数
if [ "$#" -ne 1 ]; then
    echo "使用方法: $0 '提交信息'"
    exit 1
fi
# 将参数存储在变量中
commit_message="$1"
# 执行 Git 命令
git add .
git commit -m "$commit_message"
git push origin main
  • 增加执行权限:chmod +x auto-push.sh
  • 一键推送:./auto-push.sh [commit message]

参考链接

Shawn’s Blog
Image’s Blog