使用 AWS CLI 将 Hugo 网站部署到 AWS S3

自动化将 Hugo 部署到 AWS S3

目录

使用 AWS CLI 将 Hugo 静态站点部署到 AWS S3 可以提供一个强大且可扩展的解决方案,用于托管您的网站。本指南涵盖了从初始设置到高级自动化和缓存管理策略的完整部署过程。

桌面上的彩色俄罗斯方块

由于 Hugo 发行版已从标准包中移除了 deploy 命令,使用 AWS CLI 进行部署正在成为一种主流方式。如果在本地进行部署并仍希望调用 hugo deploy,请参阅 如何安装 Ubuntu 24.04 及有用工具 中关于 extendedwithdeploy 的内容。

先决条件

在将 Hugo 网站部署到 AWS S3 之前,请确保您具备以下条件:

  • 一个准备就绪的 Hugo 网站(如果需要帮助创建一个,请查看 Hugo 快速入门指南
  • 一个具有适当权限的 AWS 账户
  • 已安装并配置 AWS CLI
  • 基本的命令行操作知识

构建您的 Hugo 网站

部署您的 Hugo 网站的第一步是生成静态文件。使用 Hugo 命令速查表 作为参考,了解可用的命令和选项。

使用优化标志构建您的网站:

hugo --gc --minify

--gc 标志会删除未使用的缓存文件,而 --minify 会压缩 HTML、CSS 和 JavaScript 以实现最佳性能。这会将静态网站生成在 public/ 目录中,这是我们部署到 S3 的内容。

配置 AWS CLI

如果您尚未配置 AWS CLI,请运行:

aws configure

您将被提示输入以下内容:

  • AWS 访问密钥 ID:您的 AWS 访问密钥
  • AWS 秘密访问密钥:您的秘密访问密钥
  • 默认区域:您首选的 AWS 区域(例如 us-east-1ap-southeast-2
  • 默认输出格式json(推荐)

对于程序访问,请确保您的 IAM 用户具有以下权限:

  • s3:PutObject
  • s3:GetObject
  • s3:DeleteObject
  • s3:ListBucket
  • cloudfront:CreateInvalidation(如果使用 CloudFront)

创建和配置 S3 存储桶

创建存储桶

使用 AWS CLI 创建 S3 存储桶:

aws s3 mb s3://your-bucket-name --region us-east-1

重要:选择一个全局唯一的存储桶名称。如果您计划使用存储桶来托管网站,并且使用自定义域名,则存储桶名称必须与您的域名名称匹配。

配置存储桶以托管静态网站

启用静态网站托管:

aws s3 website s3://your-bucket-name \
  --index-document index.html \
  --error-document 404.html

设置存储桶策略

如果未使用 CloudFront(推荐),则创建一个存储桶策略以允许公共读取访问:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

应用策略:

aws s3api put-bucket-policy \
  --bucket your-bucket-name \
  --policy file://bucket-policy.json

安全提示:如果您使用 CloudFront(推荐),您可以将 S3 存储桶访问权限限制为仅 CloudFront,从而消除对公共读取访问的需要。

使用 AWS CLI 部署到 S3

核心部署命令使用 aws s3 sync 上传您的网站:

aws s3 sync public/ s3://your-bucket-name/ \
  --delete \
  --cache-control max-age=60

关键参数说明

  • public/:本地 Hugo 输出目录
  • s3://your-bucket-name/:S3 存储桶目标
  • --delete:删除 S3 中本地不存在的文件,确保存储桶与构建内容一致
  • --cache-control max-age=60:设置缓存头(此示例中为 60 秒)

高级同步选项

为了更好地控制部署:

aws s3 sync public/ s3://your-bucket-name/ \
  --delete \
  --cache-control "public, max-age=31536000, immutable" \
  --exclude "*.html" \
  --cache-control "public, max-age=60" \
  --include "*.html" \
  --exclude "*.js" \
  --cache-control "public, max-age=31536000, immutable" \
  --include "*.js"

此示例为 HTML 文件设置不同的缓存时间(60 秒)与静态资源(如 JavaScript)(1 年),这是常见的优化策略。

设置 CloudFront 分发

虽然 S3 可以直接托管静态网站,但使用 Amazon CloudFront 作为 CDN 可提供更好的性能、安全性和全球分发。

创建 CloudFront 分发

aws cloudfront create-distribution \
  --distribution-config file://cloudfront-config.json

一个基本的 CloudFront 配置包括:

  • S3 存储桶作为源
  • 默认缓存行为
  • SSL/TLS 证书(来自 AWS 证书管理器)
  • 自定义域名配置(可选)

缓存管理策略

在通过 CloudFront 部署时,考虑以下缓存策略:

  1. 设置最大 TTL:配置 CloudFront 的最大 TTL 以控制内容在边缘位置的缓存时间
  2. 内容版本控制:在文件名中使用版本标识符(例如 style-v2.css)以强制更新缓存
  3. 缓存控制头:在 S3 同步期间设置适当的头(如上所示)
  4. 选择性清除缓存:仅清除已更改的路径,而不是整个缓存

缓存清除

部署更新后,清除 CloudFront 缓存以提供新鲜内容:

aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/*"

对于更精确的清除:

aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/index.html" "/blog/*"

成本考虑:每月前 1,000 个清除路径是免费的。之后,每个路径收费 0.005 美元。使用选择性清除以减少成本。

使用 CI/CD 自动化部署

对于小型项目,手动部署是可行的,但自动化对于生产工作流程至关重要。您可以将此部署过程与 使用 Gitea Actions 将 Hugo 网站部署到 AWS S3 或类似的 CI/CD 管道集成。

基本部署脚本

创建一个简单的部署脚本:

#!/bin/bash
set -e

# 构建 Hugo 网站
echo "Building Hugo site..."
hugo --gc --minify

# 部署到 S3
echo "Deploying to S3..."
aws s3 sync public/ s3://your-bucket-name/ \
  --delete \
  --cache-control max-age=60

# 清除 CloudFront 缓存
echo "Invalidating CloudFront cache..."
aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/*"

echo "Deployment complete!"

使其可执行并运行:

chmod +x deploy.sh
./deploy.sh

GitHub Actions 示例

对于 GitHub 仓库,创建 .github/workflows/deploy.yml

name: Deploy to AWS S3

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: 'latest'
      
      - name: Build
        run: hugo --gc --minify
      
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      
      - name: Deploy to S3
        run: |
          aws s3 sync public/ s3://your-bucket-name/ \
            --delete \
            --cache-control max-age=60          
      
      - name: Invalidate CloudFront
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
            --paths "/*"          

监控与优化

启用日志记录

配置 S3 和 CloudFront 日志记录以跟踪访问模式:

# 启用 S3 访问日志
aws s3api put-bucket-logging \
  --bucket your-bucket-name \
  --bucket-logging-status file://logging.json

设置 CloudWatch 警报

使用 CloudWatch 监控部署:

aws cloudwatch put-metric-alarm \
  --alarm-name high-error-rate \
  --alarm-description "Alert on high error rate" \
  --metric-name 4xxError \
  --namespace AWS/CloudFront \
  --statistic Sum \
  --period 300 \
  --threshold 10 \
  --comparison-operator GreaterThanThreshold

常见问题排查

文件未更新

如果更改未显示:

  1. 检查 CloudFront 缓存清除状态
  2. 验证同步命令中是否使用了 --delete 标志
  3. 清除浏览器缓存或在无痕模式下测试
  4. 检查 S3 存储桶权限

部署缓慢

优化同步性能:

  • 使用 --exclude--include 跳过不必要的文件
  • 考虑使用 --size-only 进行更快的比较
  • 使用 --cli-read-timeout--cli-write-timeout 进行并行上传

权限错误

确保您的 IAM 用户具有:

  • S3 存储桶访问权限
  • CloudFront 缓存清除权限(如适用)
  • 正确配置的存储桶策略

最佳实践总结

  1. 始终使用 --delete 以保持 S3 与本地构建同步
  2. 根据文件类型设置适当的缓存头
  3. 使用 CloudFront 进行生产部署
  4. 使用 CI/CD 管道自动化部署
  5. 监控成本 - 注意 CloudFront 缓存清除费用
  6. 版本化部署 - 为回滚方便标记发布版本
  7. 先本地测试 - 部署前验证 Hugo 构建

相关资源

如需了解更多关于 Hugo 部署的详细信息,请查看 将 Hugo 生成的网站部署到 AWS S3 的全面指南,其中涵盖了额外的部署选项和配置。

在撰写内容时,请记得使用适当的 Markdown 代码块 来展示代码示例,并参考 全面的 Markdown 速查表 获取格式指南。

有用链接

外部参考资料