阅读 1 分钟
使用 GitHub Actions 自动部署 Astro 项目到 Nginx 服务器
Astro 默认生成静态文件,每次更新文章都在本地构建再上传会比较繁琐。现在本站改为推送到 GitHub 的 main 分支后,由 GitHub Actions 自动完成检查、构建和部署。
部署结构
整个流程分为四步:
- 使用 pnpm 安装锁定版本的依赖。
- 运行 Astro 检查、静态构建和 Pagefind 索引。
- 使用专用 SSH 用户验证服务器目录权限。
- 通过 rsync 同步
dist/,并清理已经不存在的旧文件。
服务器上的部署用户没有 sudo 权限,只能写入站点目录。Nginx 继续读取静态文件,因此每次发布文章都不需要重启服务。
GitHub Actions 配置
工作流位于 .github/workflows/deploy.yml:
name: Deploy Mistwood
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: production-deployment
cancel-in-progress: false
jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 15
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Set up pnpm
uses: pnpm/action-setup@v6
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build site
run: pnpm build
- name: Configure SSH
shell: bash
run: |
set -euo pipefail
install -d -m 700 ~/.ssh
install -m 600 /dev/null ~/.ssh/id_ed25519
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519
printf '%s\n' "$DEPLOY_KNOWN_HOSTS" > ~/.ssh/known_hosts
- name: Verify deployment target
shell: bash
run: |
set -euo pipefail
ssh -p "$DEPLOY_PORT" -i ~/.ssh/id_ed25519 \
-o IdentitiesOnly=yes -o StrictHostKeyChecking=yes \
"$DEPLOY_USER@$DEPLOY_HOST" \
"test -d '$DEPLOY_PATH' && test -w '$DEPLOY_PATH'"
- name: Deploy static files
shell: bash
run: |
set -euo pipefail
rsync --archive --compress --delay-updates --delete-delay \
-e "ssh -p $DEPLOY_PORT -i ~/.ssh/id_ed25519 -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes" \
dist/ "$DEPLOY_USER@$DEPLOY_HOST:${DEPLOY_PATH%/}/"
--delete-delay 会在新文件传输完成后删除远端旧文件。这个选项很适合静态站点,但必须保证目标目录只存放当前站点的构建产物。
配置 Secrets
在仓库的 Settings > Secrets and variables > Actions 中配置:
DEPLOY_HOST:服务器域名或 IP。DEPLOY_PORT:SSH 端口。DEPLOY_USER:无 sudo 权限的部署用户。DEPLOY_PATH:Nginx 的站点目录。DEPLOY_SSH_KEY:专用部署私钥。DEPLOY_KNOWN_HOSTS:经过核对的服务器主机密钥。
不要在工作流中关闭 StrictHostKeyChecking,也不要把私钥直接写进仓库。主机密钥固定后,如果服务器身份意外变化,部署应该明确失败,而不是静默接受。
发布文章
正常提交并推送即可触发部署:
git add .
git commit -m "content: publish new post"
git push origin main
构建失败时不会连接服务器;SSH 目录校验失败时也不会执行 rsync。这样可以避免错误构建或错误路径覆盖线上文件。