PhysChen.com
主页
物理
笔记 科普 研究
教学
IB 课程
编程
笔记 项目
随笔
所感 所思
摄影
Shenzhen Portrait Cats Others Wuhan Japan
关于
主页
物理
笔记 科普 研究
编程
笔记 项目
摄影
Shenzhen Portrait Cats Others Wuhan Japan
教学
IB 课程
随笔
所感 所思
关于
文章目录
    Astro + GitHub Actions 自动化部署到个人服务器 陈华的个人主页

    文章信息

    • 标题: Astro + GitHub Actions 自动化部署到个人服务器
    • 发布时间: 2026 年 4 月 18 日
    • 最近更新: 2026 年 7 月 20 日
    • 来源: https://physchen.com/zh-Hans/programming/notes/astro-github-actions-auto-deploy-server/
    • 摘要: Astro 静态站点的本地命令、构建输出,以及通过 GitHub Actions 与 rsync 部署到个人服务器的步骤。

    目录

      Astro + GitHub Actions 自动化部署到个人服务器

      发布于 2026 年 4 月 18 日 更新于 2026 年 7 月 20 日
      English version
      • Astro
      • Git

      本文记录 Astro 静态站点从本地开发到 GitHub Actions 自动部署的完整流程⁠。部署链路为⁠:本地或 CI 执行构建 → 生成 dist/ → 通过 SSH + rsync 同步到服务器目录⁠,由 Nginx 等 Web 服务器提供静态文件服务⁠。

      1. 环境要求

      项目版本或说明
      Node.js22(⁠与 CI 保持一致⁠)
      包管理器pnpm(⁠package.json 中可通过 packageManager 字段锁定版本⁠)
      Astro5.x
      服务器开放 SSH(⁠22⁠)端口⁠,已安装 Nginx 或其他静态文件服务

      新建项目⁠:

      pnpm create astro@latest
      cd <project-name>
      pnpm install

      2. Astro 命令

      2.1 项目脚本(⁠package.json⁠)

      常见定义方式⁠:

      {
        "scripts": {
          "dev": "astro dev",
          "build": "astro build",
          "preview": "astro preview",
          "astro": "astro"
        }
      }

      对应命令⁠:

      pnpm dev       # 开发服务器,默认 http://localhost:4321
      pnpm build     # 生产构建,输出到 dist/
      pnpm preview   # 在本地预览 dist/ 的构建结果

      部分项目会在 build 前增加资源同步⁠、搜索索引生成等步骤⁠,例如 pnpm assets:sync && astro build && pagefind --site dist⁠。CI 中应执行与线上一致的 pnpm run build⁠,而不是单独跑 astro build⁠,除非已确认两者等价⁠。

      2.2 Astro CLI

      通过 pnpm astro 调用⁠:

      pnpm astro dev [--host 0.0.0.0] [--port 4321]
      pnpm astro build
      pnpm astro preview [--host 0.0.0.0] [--port 4321]
      pnpm astro check          # 结合 @astrojs/check 做类型与模板检查
      pnpm astro sync           # 生成 .astro/types.d.ts
      pnpm astro add <integration>

      开发服务器的监听地址与端口可在 astro.config.mjs 的 server.host⁠、server.port 中配置⁠,也可通过 astro dev 的 --host⁠、--port 命令行选项临时覆盖⁠。

      2.3 构建产物

      astro build 在 output: 'static' 模式下将所有静态文件写入项目根目录下的 dist/⁠。部署时上传的是 dist/ 内的内容⁠,不是源码目录⁠。

      本地验证构建结果⁠:

      pnpm build
      pnpm preview

      3. 关键配置

      astro.config.mjs 中与部署相关的字段⁠:

      import { defineConfig } from 'astro/config';
      
      export default defineConfig({
        output: 'static',
        site: 'https://example.com',
      });
      字段作用
      output: 'static'生成纯静态 HTML/CSS/JS⁠,适合 rsync 部署
      site站点根 URL⁠,供 sitemap⁠、RSS⁠、canonical 等使用⁠;改为实际域名

      4. 服务器⁠:SSH 密钥

      在可信的管理终端上生成专用于部署的密钥对⁠。不要在服务器上生成后再把私钥复制出来⁠;服务器只需要保存公钥⁠:

      ssh-keygen -m PEM -t rsa -b 4096 -C "github-actions-deploy" -f ./github_actions

      生成时不设置 passphrase(⁠GitHub Actions 无法交互输入⁠)⁠。

      把 github_actions.pub 安全地复制到服务器⁠,将公钥内容追加到部署用户的 authorized_keys⁠,并设置目录权限⁠:

      cat /path/to/github_actions.pub >> ~/.ssh/authorized_keys
      chmod 700 ~/.ssh
      chmod 600 ~/.ssh/authorized_keys

      权限不正确时⁠,sshd 会拒绝密钥登录⁠。

      导出私钥⁠,供下一节填入 GitHub Secret⁠:

      cat ./github_actions

      输出须包含 -----BEGIN ... PRIVATE KEY----- 与 -----END ... PRIVATE KEY----- 行⁠。

      5. GitHub Secrets

      在仓库 Settings → Secrets and variables → Actions 中新建⁠:

      名称值
      SERVER_HOST服务器 IP 或域名
      SERVER_USERSSH 登录用户名
      SERVER_SSH_KEY第 4 节生成的私钥全文

      私钥与服务器密码不应出现在 workflow 文件或 Git 提交记录中⁠,仅通过 ${{ secrets.* }} 引用⁠。

      6. GitHub Actions Workflow

      在项目根目录创建 .github/workflows/deploy.yml⁠:

      name: Build and Deploy Astro
      
      on:
        push:
          branches:
            - main
      
      jobs:
        build-and-deploy:
          runs-on: ubuntu-latest
          permissions:
            contents: read
          concurrency:
            group: deploy-${{ github.ref }}
            cancel-in-progress: false
      
          steps:
            - name: Checkout Code
              uses: actions/checkout@v6
      
            - name: Setup pnpm
              uses: pnpm/action-setup@v6
      
            - name: Setup Node.js
              uses: actions/setup-node@v6
              with:
                node-version: '22'
                cache: 'pnpm'
      
            - name: Install Dependencies
              run: pnpm install --frozen-lockfile
      
            - name: Restore Image Caches
              uses: actions/cache@v5
              with:
                path: |
                  node_modules/.astro/assets
                  public/generated-previews
                key: ${{ runner.os }}-image-cache-${{ hashFiles('src/assets/images/**/*.avif', 'src/assets/images/config.json', 'src/assets/photos/**/*.avif', 'src/assets/photos/**/*.json', 'src/utils/asset-image.ts', 'src/utils/public-image.ts', 'src/utils/photography.ts', 'src/utils/hero-image.ts', 'astro.config.mjs', 'package.json', 'pnpm-lock.yaml') }}
                restore-keys: |
                  ${{ runner.os }}-image-cache-
      
            - name: Build Astro Site
              run: pnpm run build
      
            - name: Check Deploy Host Connectivity
              env:
                REMOTE_HOST: ${{ secrets.SERVER_HOST }}
              run: |
                set -eu
                getent ahosts "$REMOTE_HOST"
                timeout 10 bash -c 'cat < /dev/null > /dev/tcp/'"$REMOTE_HOST"'/22'
      
            - name: Deploy to Server
              uses: easingthemes/ssh-deploy@v6.0.1
              with:
                SSH_PRIVATE_KEY: ${{ secrets.SERVER_SSH_KEY }}
                ARGS: "-rl --delete --info=progress2,stats2 --human-readable -i --exclude=files/images-originals/*** --exclude=files/photos-originals/***"
                SOURCE: "dist/"
                REMOTE_HOST: ${{ secrets.SERVER_HOST }}
                REMOTE_USER: ${{ secrets.SERVER_USER }}
                TARGET: "/var/www/your-site"

      6.1 步骤说明

      步骤说明
      concurrency同一分支的部署按顺序执行⁠,避免新推送在 rsync 写入过程中取消旧任务而留下不完整站点
      permissions: contents: read将工作流自带令牌限制为检出源码所需的只读权限
      pnpm/action-setup省略 version 时读取 package.json 的 packageManager 字段⁠,避免 CI 与本地 pnpm 版本漂移
      pnpm install --frozen-lockfile按锁文件安装⁠,不更新依赖版本
      Restore Image Caches缓存 Astro 图片处理产物⁠;hashFiles 列表需按项目实际资源路径调整⁠,无图片管线时可删除此步
      pnpm run build执行 package.json 中定义的完整构建流程
      Check Deploy Host Connectivity部署前检查 DNS 解析与 22 端口连通性⁠;不需要时可删除
      easingthemes/ssh-deploy在 runner 上对 SOURCE 目录执行 rsync⁠,通过 SSH 写入 TARGET

      6.2 rsync 参数

      ARGS 中各选项含义⁠:

      选项含义
      -r递归
      -l保留符号链接
      --delete删除接收端存在但发送端不存在的文件
      -i输出逐文件变更摘要⁠,即 --itemize-changes⁠;SSH 传输由部署 Action 配置
      --exclude=...排除指定路径⁠,不纳入同步

      SOURCE: "dist/" 末尾斜杠表示同步 dist/ 内部文件到 TARGET 根目录⁠,不会在远端产生 dist/dist/ 嵌套⁠。

      TARGET 改为服务器上网站根目录的实际路径⁠。

      示例使用已发布的 Action 主版本标签⁠,便于阅读和更新⁠。安全要求较高的仓库可进一步把第三方 Action 固定到审查过的完整提交 SHA⁠,并通过依赖更新工具定期升级⁠;不要在生产工作流中长期跟随可变的 @main⁠。

      7. 服务器 Web 配置

      Nginx 将域名指向部署目录的示例⁠:

      server {
          listen 80;
          server_name example.com;
          root /var/www/your-site;
          index index.html;
      
          location / {
              try_files $uri $uri/ $uri.html =404;
          }
      }

      HTTPS 需另行配置证书(⁠如 Let's Encrypt⁠)⁠。root 路径须与 workflow 中 TARGET 一致⁠。

      若服务器目标目录中还有手动维护的内容(⁠如原图存储⁠)⁠,应使用 rsync 的 --exclude 明确保护相应路径⁠,避免 --delete 在清理接收端时将其删除⁠。首次启用或修改删除规则时⁠,宜先用 --dry-run 检查将要传输和删除的文件⁠。

      8. 部署流程

      1. 本地修改代码⁠,pnpm build 确认构建通过⁠。
      2. 提交并 push 到 main⁠。
      3. GitHub Actions 自动执行 workflow⁠。
      4. 在仓库 Actions 页查看任务状态⁠;失败时展开对应步骤的日志定位错误⁠。

      手动在服务器上首次部署时⁠,可先本地构建再 rsync⁠:

      pnpm build
      rsync -rl --delete \
        --exclude='files/images-originals/***' \
        --exclude='files/photos-originals/***' \
        -e ssh dist/ user@host:/var/www/your-site/

      若目标目录没有这些服务器专属路径⁠,可移除对应排除项⁠;若还有其他仅存在于服务器端的内容⁠,应继续添加排除规则⁠。首次执行时先加入 --dry-run 核对结果⁠。

      9. 常见问题

      密钥登录失败

      • 检查 ~/.ssh 权限是否为 700⁠,authorized_keys 是否为 600⁠。
      • 确认 GitHub Secret 中的私钥完整⁠,无多余空格或换行缺失⁠。
      • 确认 SERVER_USER 与服务器实际用户一致⁠。

      构建通过但站点未更新

      • 确认 TARGET 与 Nginx root 指向同一目录⁠。
      • 检查 rsync 是否因权限不足写入失败(⁠查看 Actions 日志⁠)⁠。

      --delete 删除了服务器上的额外文件

      • --delete 会使目标目录与 dist/ 严格一致⁠。不应出现在构建产物中⁠、但需保留在服务器上的路径⁠,须通过 --exclude 排除⁠。

      开发端口被占用

      pnpm astro dev --port 4322

      或在 astro.config.mjs 中修改 server.port⁠。

      上一篇 JavaScript 1. 基础语法 2026 年 7 月 10 日 下一篇 Git 常用命令速查 2026 年 2 月 1 日
      © 2026 CHEN Hua All rights reserved
      闽ICP备2026003335号 · 粤公网安备44030002014022号
      © Hua Chen / PhysChen.com