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

AWS环境下CloudFront到LoadBalancer的WordPress 301重定向问题求助

问题描述

访问example.com域名时,会触发301重定向至LoadBalancer地址(loadbalancer.xx.xx.com),但网站应通过原域名提供服务。

基础设施架构

ECS(Dockerfile)(端口80) -> LoadBalancer(端口80) -> CloudFront(端口443) -> example.com

示例重定向场景:

example.com/wp-admin/install.php ->301-> loadbalancer.xx.xx.com/wp-admin/install.php

已尝试的解决方法
  • 完全清理.htaccess文件,但无效;
  • 在wp-config-docker.php中添加以下配置:

    define('WP_HOME', getenv_docker('WP_HOME', ''));
    define('WP_SITEURL', getenv_docker('WP_SITEURL', ''));
    此时访问example.com会正确重定向至example.com/wp-admin/install.php,但填写安装表单后,再次触发301重定向到LoadBalancer地址:
    https://example.com -> http://loadbalancer.xx.xx.com

  • 检查数据库导出文件file.sql,未发现loadbalancer.xx.xx.com相关条目。
相关代码

使用官方WordPress php8.2/apache版本镜像

ECS任务定义(Terraform)

# ECS Task Definition
resource "aws_ecs_task_definition" "woocommerce_task" {
  depends_on = [ aws_efs_access_point.wp_content ]
  family                   = var.task_family
  network_mode             = var.network_mode
  requires_compatibilities = var.task_compatibilities
  cpu                      = var.task_cpu
  memory                   = var.task_memory
  execution_role_arn       = aws_iam_role.ecs_execution_role.arn
  task_role_arn           = aws_iam_role.ecs_task_role.arn
  container_definitions = jsonencode([
    {
      name      = var.container_name,
      image     = "${var.ecr_repository_url}:${var.container_image_tag}",
      # user = "33:33",
      user = "0:0",
      essential = true,
      mountPoints: [{
        "sourceVolume": "wp-content",
        "containerPath": "/var/www/html/"
        # "containerPath": "/var/www/html/wp-content/"
      }],
      environment = [
        {
          name  = "WORDPRESS_DB_NAME",
          value = var.db_name
        },
        {
          name  = "WORDPRESS_DB_HOST",
          value = "${var.db_host}:3306"
        },
        {
          name  = "WORDPRESS_DB_USER",
          value = "XXXX"
        },
        {
          name  = "WORDPRESS_DB_PASSWORD",
          value = "XXXX"
        },
        {
          name  = "TAR_OPTIONS",
          value = "--no-same-owner"
        },
        # {
        #   name  = "WP_HOME",
        #   value = "https://example.com"
        # },
        # {
        #   name  = "WP_SITEURL",
        #   value = "https://example.com"
        # }
      ],
      portMappings = [{
        containerPort = var.container_port,
        hostPort      = var.container_port,
        protocol      = "tcp"
      }],
      logConfiguration = {
        logDriver = "awslogs",
        options = {
          "awslogs-group"         = aws_cloudwatch_log_group.ecs_logs.name,
          "awslogs-region"        = var.aws_region,
          "awslogs-stream-prefix" = "ecs"
        }
      }
    }
  ])
}

LoadBalancer定义(Terraform)

resource "aws_lb" "nan_lb" {
  name                       = var.lb_name
  internal                   = false # Set to false if you want to expose the load balancer to the internet. Cloudfront need it.
  load_balancer_type         = "application"
  security_groups = [aws_security_group.allow_all.id]
  enable_deletion_protection = false
  subnets                    = [var.subnet_a_id, var.subnet_b_id]
  access_logs {
    bucket  = aws_s3_bucket.lb_logs.id
    enabled = true
  }
}

CloudFront定义(Terraform)

# CloudFront Distribution Configuration
resource "aws_cloudfront_distribution" "cloudfront_dist" {
  depends_on   = [aws_wafv2_web_acl.nan_web_acl]
  provider     = aws.east
  aliases      = [var.domain_name, "www.${var.domain_name}"]
  http_version = "http2and3"
  web_acl_id   = aws_wafv2_web_acl.nan_web_acl.arn
  # https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PriceClass.html
  price_class = "PriceClass_100"

  origin {
    domain_name = aws_lb.nan_lb.dns_name
    origin_id   = "nan_lb"

    custom_origin_config {
      http_port                = 80
      https_port               = 80
      origin_protocol_policy   = "http-only"
      origin_ssl_protocols     = ["TLSv1.2"]
      origin_keepalive_timeout = 5
      origin_read_timeout      = 30
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  comment             = "CloudFront distribution for nan-woocommerce"
  default_root_object = "index.php"
  # default_root_object = "index.html"

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD", "POST", "OPTIONS", "PUT", "PATCH", "DELETE"]
    cached_methods   = ["GET", "HEAD", "OPTIONS"]
    target_origin_id = "nan_lb"
    compress         = true

    forwarded_values {
      query_string = true
      query_string_cache_keys = ["*"]

      headers = ["Origin"]

      cookies {
        forward           = "whitelist"
        whitelisted_names = ["comment_*", "wordpress_*", "wp-settings-*"] 
      }
    }

    viewer_protocol_policy = "redirect-to-https"
    min_ttl                = 0
    default_ttl            = 300
    max_ttl                = 31536000
  }
  ..........
  ..............
}
问题根源与解决方法

问题根源

  1. Host头未正确转发:CloudFront默认不会将用户访问的原始Host头传递给后端LoadBalancer,导致WordPress识别的请求域名是LoadBalancer的地址,进而生成该域名的重定向链接。
  2. 反向代理配置缺失:WordPress运行在CloudFront和LoadBalancer组成的反向代理之后,未配置识别真实请求的协议与域名,导致用后端地址生成URL。
  3. 环境变量未启用:wp-config-docker.php中配置了读取WP_HOME和WP_SITEURL环境变量,但ECS任务中未启用这些配置,安装过程中WordPress仍会基于请求Host设置站点地址。

解决步骤

1. 配置CloudFront转发Host头

修改CloudFront的forwarded_values部分,添加Host到转发头列表:

forwarded_values {
  query_string = true
  query_string_cache_keys = ["*"]

  headers = ["Origin", "Host"] # 新增Host头转发

  cookies {
    forward           = "whitelist"
    whitelisted_names = ["comment_*", "wordpress_*", "wp-settings-*"] 
  }
}

2. 启用ECS中的WP_HOME和WP_SITEURL环境变量

取消ECS任务定义中WP_HOME和WP_SITEURL的注释:

{
  name  = "WP_HOME",
  value = "https://example.com"
},
{
  name  = "WP_SITEURL",
  value = "https://example.com"
}

3. 添加反向代理识别配置到wp-config-docker.php

添加以下代码让WordPress识别CloudFront传递的真实请求信息:

// 识别HTTPS协议
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
    $_SERVER['HTTPS'] = 'on';
}

// 设置真实请求Host
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}

// 强制后台使用HTTPS
define('FORCE_SSL_ADMIN', true);

4. 重新部署并验证

  • 应用Terraform配置变更,重新部署ECS任务、CloudFront和LoadBalancer。
  • 清空浏览器缓存,重新访问example.com完成安装,验证重定向是否正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:20:02