You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hugo部署S3+CloudFront无法自动跳转index.html的Terraform配置问题

问题解决:Hugo子路径访问403的Terraform配置修改

核心问题分析

你的配置中default_root_object = "index.html"仅对根路径/生效,访问子路径如/blog/post-1时,CloudFront会直接向S3请求blog/post-1对象,但Hugo生成的静态文件实际是blog/post-1/index.html,导致S3返回访问拒绝。同时viewer_certificate配置存在冲突(同时启用默认证书和自定义ACM证书),需要同步修正。

修改后的完整配置

1. 添加Lambda@Edge路径重写函数

创建Origin Request类型的Lambda@Edge函数,自动为无后缀的请求路径追加/index.html(Lambda@Edge必须部署在us-east-1区域):

# 新增us-east-1区域的AWS Provider
provider "aws" {
  alias  = "us_east_1"
  region = "us-east-1"
}

# Lambda函数角色(Edge函数需额外信任edgelambda服务)
resource "aws_iam_role" "lambda_edge_role" {
  provider = aws.us_east_1
  name     = "lambda-edge-hugo-path-rewrite-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = [
            "lambda.amazonaws.com",
            "edgelambda.amazonaws.com"
          ]
        }
      }
    ]
  })
}

# 附加基础执行权限
resource "aws_iam_role_policy_attachment" "lambda_edge_basic_execution" {
  provider = aws.us_east_1
  role     = aws_iam_role.lambda_edge_role.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

# Lambda@Edge函数本体
resource "aws_lambda_function" "cloudfront_path_rewrite" {
  provider      = aws.us_east_1
  filename      = "lambda_function_payload.zip"
  function_name = "cloudfront-hugo-path-rewrite"
  role          = aws_iam_role.lambda_edge_role.arn
  handler       = "index.lambda_handler"
  runtime       = "nodejs20.x"
  source_code_hash = filebase64sha256("lambda_function_payload.zip")
}

Lambda函数代码(需打包为lambda_function_payload.zip)
创建index.js文件,写入以下逻辑:

exports.lambda_handler = async (event) => {
    const request = event.Records[0].cf.request;
    const uri = request.uri;

    // 对无文件后缀的路径追加/index.html
    if (!uri.match(/\.\w+$/) && !uri.endsWith('/')) {
        request.uri = `${uri}/index.html`;
    } else if (uri.endsWith('/')) {
        request.uri = `${uri}index.html`;
    }

    return request;
};

2. 修正CloudFront分发配置

更新aws_cloudfront_distribution资源,添加Lambda@Edge触发器,并修复证书配置冲突:

resource "aws_cloudfront_distribution" "my_cloudfront" {
  depends_on = [
    aws_s3_bucket.my_site_bucket,
    aws_lambda_function.cloudfront_path_rewrite
  ]

  origin {
    domain_name = aws_s3_bucket.my_site_bucket.bucket_regional_domain_name
    origin_id   = "s3-cloudfront"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"
  aliases             = [var.domain_name]

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "s3-cloudfront"

    forwarded_values {
      query_string = false
      cookies { forward = "none" }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400

    # 关联Lambda@Edge路径重写触发器
    lambda_function_association {
      event_type   = "origin-request"
      lambda_arn   = "${aws_lambda_function.cloudfront_path_rewrite.arn}:${aws_lambda_function.cloudfront_path_rewrite.version}"
      include_body = false
    }
  }

  price_class = "PriceClass_200"

  viewer_certificate {
    # 禁用默认证书,使用自定义ACM证书
    cloudfront_default_certificate = false
    acm_certificate_arn            = aws_acm_certificate.my_site.arn
    ssl_support_method             = "sni-only"
    minimum_protocol_version       = "TLSv1.2_2021" # 推荐使用更安全的协议版本
  }

  tags = local.cdn_tags
}

3. 可选:添加兜底自定义错误响应

如果Lambda覆盖场景存在遗漏,可添加自定义错误响应,将403/404错误映射到index.html:

resource "aws_cloudfront_distribution" "my_cloudfront" {
  # ... 其他配置 ...

  custom_error_response {
    error_code         = 403
    response_code      = 200
    response_page_path = "/index.html"
  }

  custom_error_response {
    error_code         = 404
    response_code      = 200
    response_page_path = "/index.html"
  }
}

部署步骤

  1. 将上述Lambda代码打包为lambda_function_payload.zip
  2. 执行terraform init、terraform plan、terraform apply部署配置
  3. 等待CloudFront分发更新完成(通常需10-15分钟)

内容的提问来源于stack exchange,提问作者JPFrancoia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 08:36:18