github action 构建推送服务器

Published on

主题

本指南介绍如何使用 GitHub Actions 将静态站点从 release-out 分支构建并推送到远程 Linux(ubantu/debian/centos...) 服务器(部署通过 nginx 服务配置静态文件,不包含此部分)

目录

  1. 工作流文件路径
  2. GitHub Actions 触发条件
  3. 当前 workflow 配置说明
  4. workflow 中各项值的含义与获取方式
  5. 如何配置 GitHub Secrets
  6. 服务器端配置
  7. 排错与注意事项

1. 工作流文件路径

当前工作流文件:

  • .github/workflows/release-out-deploy.yml

2. GitHub Actions 触发条件

该 workflow 设置为:

on:
  push:
    branches:
      - release-out

这意味着:

  • 仅当代码推送到 release-out 分支时才会触发部署流程。

3. 当前 workflow 配置说明

当前工作流内容如下:

name: release-out deployment

on:
  push:
    branches:
      - release-out

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '24'

      - name: Install dependencies
        run: npm install

      - name: Build and export static site
        run: npm run build:export

      - name: Start SSH agent
        uses: webfactory/ssh-agent@v0.7.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Add SSH known hosts
        run: |
          mkdir -p ~/.ssh
          printf '%s\n' "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts
          chmod 600 ~/.ssh/known_hosts

      - name: Deploy directory to target server
        env:
          DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
          DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
          DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
          DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
          UPLOAD_DIR: out
        run: |
          mkdir -p ~/.ssh
          if [ -z "$DEPLOY_PORT" ]; then
            DEPLOY_PORT=22
          fi
          rsync -avz --delete -e "ssh -p $DEPLOY_PORT" "$UPLOAD_DIR/" "$DEPLOY_USER"@"$DEPLOY_HOST":"$DEPLOY_PATH"

4. workflow 中各项值的含义与获取方式

4.1 runs-on: ubuntu-latest

  • 表示 GitHub Actions 在 GitHub 官方提供的 Ubuntu Runner 上执行。
  • 这是 CI 机器,不是目标服务器。
  • 之前使用 debian-latest 会导致 runner 找不到或排队问题,因此改为 ubuntu-latest。

4.2 actions/checkout@v4

  • 将当前仓库代码检出到 runner 上。

4.3 actions/setup-node@v4 + node-version: '24'

  • 在 runner 上安装 Node.js 24。
  • 该版本与本地 node -v 输出一致。
  • 如果构建过程出现兼容问题,也可以改成 18 或 20,但当前配置已保持与本地一致。

4.4 npm install

  • 安装项目依赖。
  • 这个步骤会读取仓库 package.json。

4.5 npm run build:export

  • 执行构建并导出静态站点。
  • 需要在 package.json 中定义:
"build:export": "next build && next export && node ./scripts/generate-sitemap"

4.6 webfactory/ssh-agent@v0.7.0

  • 将私钥加载到 GitHub runner 的 SSH agent 中。
  • 该 action 只支持输入:
    • ssh-private-key
    • ssh-auth-sock
    • log-public-key
  • 因此我们将 SSH_KNOWN_HOSTS 改为手动写入 ~/.ssh/known_hosts。

4.7 SSH_KNOWN_HOSTS

  • 必须是远程服务器 SSH host key 的内容。
  • 通过以下命令获取:
ssh-keyscan -H -p <DEPLOY_PORT> <DEPLOY_HOST>
  • 替换 <DEPLOY_HOST> 为实际服务器地址,例如:
    • 123.45.67.89
    • myserver.example.com
  • 替换 <DEPLOY_PORT> 为 SSH 端口,例如:
    • 22(默认端口)
    • 2222

示例:

ssh-keyscan -H -p 2222 123.45.67.89

输出示例:

[123.45.67.89]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy...
[123.45.67.89]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICq...

请把输出的整行内容全部复制到 SSH_KNOWN_HOSTS Secret 中。

4.8 DEPLOY_USER

  • 远程服务器登录用户名。
  • 例如:root、debian、ubuntu、deploy。
  • 由在服务器上创建或配置的账号决定。

4.9 DEPLOY_HOST

  • 远程服务器地址。
  • 可以是 IP,如 123.45.67.89,也可以是域名,如 your-host.example.com。

4.10 DEPLOY_PATH

  • 文件部署目标目录。
  • 例如:/var/www/html、/home/deploy/www、/srv/www/gallery。

4.11 DEPLOY_PORT

  • 远程 SSH 端口。
  • 默认 SSH 端口是 22。
  • 如果服务器 SSH 端口改为 2222,请在 Secret 中填 2222。
  • 如果不设置该值,workflow 会自动使用 22。

4.12 UPLOAD_DIR: out

  • next export 的默认静态输出目录是 out。
  • 这个值指示要将 out/ 目录内容同步到远程服务器。

4.13 rsync -avz --delete -e "ssh -p $DEPLOY_PORT" ...

命令含义:

  • -a:归档模式,保留文件权限、时间等
  • -v:显示详细输出
  • -z:传输时压缩
  • --delete:远端目录中多余文件会被删除,保持与本地一致
  • -e "ssh -p $DEPLOY_PORT":通过指定 SSH 端口进行连接

5. 如何配置 GitHub Secrets

请在仓库 Settings -> Secrets and variables -> Actions 中添加以下 Secrets:

  • SSH_PRIVATE_KEY

    • 远程服务器登录所用的私钥内容
    • 私钥格式通常是 -----BEGIN OPENSSH PRIVATE KEY----- 开头
  • SSH_KNOWN_HOSTS

    • 通过 ssh-keyscan 获取的远程服务器 host key
    • 示例:
      [123.45.67.89]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy...
      [123.45.67.89]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICq...
      
  • DEPLOY_USER

    • 远程登录用户名
  • DEPLOY_HOST

    • 远程服务器 IP 或域名
  • DEPLOY_PATH

    • 远程目标目录
  • DEPLOY_PORT

    • SSH 端口,如果是 22 可留空或不配置

6. 服务器端配置

目标服务器是 Debian 系统时,推荐做以下准备:

6.1 安装 SSH 服务

如果尚未安装:

sudo apt update
sudo apt install -y openssh-server

6.2 安装 rsync

rsync 必须安装在远程服务器上,否则 rsync 连接会报错:

zsh:1: command not found: rsync

安装命令:

sudo apt update
sudo apt install -y rsync

6.3 检查 SSH 端口

默认端口:22

如果修改了 SSH 端口,例如 2222,请在 /etc/ssh/sshd_config 中确认:

Port 2222

然后重启 SSH:

sudo systemctl restart ssh

6.4 验证远程连接

推荐本地先验证:

ssh -i /path/to/private_key -p <DEPLOY_PORT> <DEPLOY_USER>@<DEPLOY_HOST>

如果本地能登录,说明私钥、端口、用户名、主机都正确。

6.5 验证远程 rsync

ssh -i /path/to/private_key -p <DEPLOY_PORT> <DEPLOY_USER>@<DEPLOY_HOST> 'rsync --version'

如果返回版本信息,则远程 rsync 已安装。

7. 排错与注意事项

7.1 Host key verification failed

原因:SSH_KNOWN_HOSTS 的内容不正确或未写入 ~/.ssh/known_hosts。

  • 正确写法是使用 ssh-keyscan -H -p <DEPLOY_PORT> <DEPLOY_HOST> 的输出
  • 如果 port 为 22,也可写成 ssh-keyscan -H <DEPLOY_HOST>。

7.2 rsync: connection unexpectedly closed + command not found: rsync

原因:远端服务器没有安装 rsync。

解决方法:

sudo apt update
sudo apt install -y rsync

7.3 Permission denied (publickey)

原因:SSH_PRIVATE_KEY 与远程服务器公钥不匹配,或远程用户没有正确权限。

  • 检查私钥是否对应远端 .ssh/authorized_keys
  • 检查 DEPLOY_USER 是否有登录权限

7.4 waiting for runner 或 Queued

  • 确认 workflow 触发分支是否为 release-out
  • 确认 GitHub Actions 在仓库设置中已启用
  • 确认组织策略或额度没有限制 Actions

7.5 Node 版本兼容性

当前 workflow 使用 node-version: '24'。

  • 这是为了与本地 v24.13.0 保持一致。
  • 如果遇到 Next 12 构建兼容问题,可以改为 18 或 20。

8. 总结

该 GitHub Actions workflow 已经完成以下流程:

  1. 在 GitHub runner 上检出仓库
  2. 安装 Node.js 24 和项目依赖
  3. 执行 npm run build:export 生成静态站点
  4. 加载 SSH 私钥
  5. 将 SSH_KNOWN_HOSTS 写入 ~/.ssh/known_hosts
  6. 使用 rsync 将 out/ 内容部署到远程服务器

只要正确配置了 GitHub Secrets、远程服务器的 SSH/rsync 环境,并确保 release-out 分支推送成功,部署流程即可正常运行。