前言

假如你经常更新博客内容,每次写完文章后还要手动登录服务器执行 rsync 命令来部署,就显得非常麻烦了。更理想的情况是:每次 push 代码到 GitHub 后,GitHub Actions 自动帮我们构建 Hugo 站点并同步到服务器上,这样我们就可以专注于写作,而不必担心部署细节。

什么是 GitHub Actions

GitHub Actions 是 GitHub 提供的一套 CI/CD(持续集成/持续部署)工具,允许我们在代码仓库中定义自动化工作流程。当特定事件发生时(例如 push、pull request、release 等),GitHub Actions 就会触发相应的工作流程,执行预定义的任务。我们可以使用 GitHub Actions 来自动化构建 Hugo 站点,并将生成的静态文件部署到远程服务器上。

准备工作

要使用 GitHub Actions 自动部署 Hugo 博客,我们需要准备以下几个方面:

  1. 远程服务器:你需要有一台远程服务器,已经安装了 Nginx 或 Apache,并且配置好了网站根目录(例如 /var/www/html/)。
  2. GitHub 仓库:你需要在 GitHub 上创建一个仓库,用来存放你的博客源码。这个仓库将作为 GitHub Actions 的触发源,当你 push 代码到这个仓库时,GitHub Actions 就会自动执行部署流程。
  3. SSH 密钥:为了让 GitHub Actions 能够安全地连接到你的远程服务器并执行部署操作,你需要生成一对 SSH 密钥,并将公钥添加到服务器的 ~/.ssh/authorized_keys 文件中,同时将私钥存储在 GitHub 仓库的 Secrets 中。

什么是 SSH 密钥

首先,我们需要知道什么是 SSH 协议。SSH(Secure Shell)是一种网络协议,用于在不安全的网络上安全地访问远程计算机。SSH 使用公钥加密技术来验证用户身份和保护数据传输的安全性。 SSH 密钥对由两部分组成:公钥和私钥。公钥可以公开分享,而私钥必须保密。使用 SSH 密钥对进行身份验证时,用户将私钥保存在本地计算机上,并将公钥上传到远程服务器。当用户尝试连接到服务器时,服务器会使用公钥来验证用户的身份,如果验证成功,用户就可以访问服务器。

在我们的部署流程中,GitHub Actions 需要使用 SSH 密钥来连接到远程服务器并执行部署命令。因此,我们需要生成一对 SSH 密钥,并将公钥添加到服务器的 ~/.ssh/authorized_keys 文件中,同时将私钥存储在 GitHub 仓库的 Secrets 中,以便 GitHub Actions 可以安全地访问服务器。生成 SSH 密钥的方法将在下面介绍。

配置 SSH 密钥

接下来,我们在远程服务器上生成 SSH 密钥对,并将公钥添加到 ~/.ssh/authorized_keys 文件中。同时,我们将私钥存储在 GitHub 仓库的 Secrets 中,以便 GitHub Actions 可以使用它来连接服务器。

生成密钥对

  1. 在服务器上执行以下命令生成 SSH 密钥对:
bash
ssh-keygen -t rsa -b 4096 -C "github-actions"
  1. 给公钥授权 生成完成后,公钥会保存在 ~/.ssh/id_rsa.pub 文件中。你需要将这个公钥的内容添加到服务器的 ~/.ssh/authorized_keys 文件中,以授权 GitHub Actions 访问服务器。
bash
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
  1. 获取私钥内容 私钥会保存在 ~/.ssh/id_rsa 文件中。你需要将这个文件的内容复制到 GitHub 仓库的 Secrets 中,命名为 DEPLOY_KEY。 首先,使用以下命令查看私钥内容:
bash
cat ~/.ssh/id_rsa

(请妥善保管并记录私钥内容,不要泄露。)

配置 GitHub Secrets

为了让 GitHub Actions 能够安全地访问你的服务器,你需要将私钥存储在 GitHub 仓库的 Secrets 中。按照以下步骤操作:

  1. 进入 Secrets 设置 在浏览器中打开你的代码仓库(例如 你的用户名/你的仓库名),点击顶部的 Settings 选项卡。 在左侧菜单栏向下滑动,找到 Secrets and variables,点击展开后选择 Actions。

  2. 添加三个机密变量 点击页面上绿色的 New repository secret 按钮,我们需要依次添加以下三个变量(注意 Name 必须全部大写,不能有拼写错误):

第一个变量(服务器 IP):

Name: SERVER_IP

Secret: (你的服务器 IP 地址)

点击 Add secret 保存。

第二个变量(登录用户名):

Name: SERVER_USER

Secret: root(如果你使用非 root 用户登录,请填写对应的用户名)

点击 Add secret 保存。

第三个变量(私钥):

Name: DEPLOY_KEY

Secret: (将刚才保存的那一整段私钥原封不动地粘贴进来)

点击 Add secret 保存。

编写 GitHub Actions Workflow

接下来,我们需要定义 GitHub Actions 的工作流程,告诉它在每次 push 代码到 main 分支时,如何构建 Hugo 站点并将生成的静态文件部署到服务器上。在项目根目录创建 .github/workflows/deploy.yml,并添加以下内容:

yaml
name: Deploy Hugo Site to Aliyun

# 触发条件:当你将代码推送到 main 分支时,自动触发此工作流
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: 1. Checkout Code
        uses: actions/checkout@v4
        with:
          submodules: true  # 必须为 true,否则无法拉取到你配置的主题文件
          fetch-depth: 0    # 拉取所有历史记录,保证文章的修改日期等功能正常读取

      - name: 2. Setup Hugo Environment
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: 'latest'
          extended: true  # 必须为 true,你的主题需要 Hugo 扩展版来编译样式

      - name: 3. Build Web Static Files
        run: hugo --minify

      - name: 4. Deploy to Aliyun Server
        uses: easingthemes/ssh-deploy@main
        env:
          SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_KEY }}
          ARGS: "-avz --delete"  # --delete 参数确保本地删除的文章,服务器端也会同步删除
          SOURCE: "public/"      # 本地需要上传的成品文件夹
          REMOTE_HOST: ${{ secrets.SERVER_IP }}
          REMOTE_USER: ${{ secrets.SERVER_USER }}
          TARGET: "/var/www/html/" # 你的 Nginx 网站根目录

推送测试

提交代码后,去 GitHub 仓库的 Actions 标签页查看运行状态。每次 push 到 main 分支都会自动触发构建和部署。如果部署成功,你的博客就会自动更新了!

如果遇到 Permission denied (publickey) 错误,检查公钥是否正确追加到服务器的 authorized_keys、私钥是否完整存入 GitHub Secrets(注意不要遗漏开头和结尾的 ----- 行)。

结语

通过以上步骤,我们成功地使用 GitHub Actions 实现了 Hugo 博客的自动部署。每次更新内容后,只需 push 代码,GitHub Actions 就会自动构建并同步到服务器上,让我们专注于写作,而不必担心部署细节了。希望这篇教程能帮助你搭建自己的 CI/CD 流水线,提升博客的维护效率!