How to serve WordPress behind CloudFront over HTTPS

Serving WordPress behind Amazon CloudFront over HTTPS keeps the public site, login page, and admin redirect chain on one secure hostname while letting CloudFront terminate viewer TLS at the edge. It also avoids the common breakage where browsers reach the CDN on HTTPS but WordPress still emits plain-HTTP redirects, cookies, or asset URLs.

CloudFront decides how browsers reach the distribution through Viewer Protocol Policy and how the distribution reaches the origin through Origin Protocol Policy, origin request policies, and optional custom origin headers. WordPress makes its own scheme decision through WP_HOME, WP_SITEURL, FORCE_SSL_ADMIN, and the request variables that feed is_ssl(), so the CDN and the origin need to agree on the public hostname and on which trusted header proves the original viewer protocol.

A stable deployment starts with a CloudFront distribution that already presents a certificate for the public hostname and receives that hostname in DNS. From there, the practical fix is to keep WordPress aligned to the final HTTPS URL, enforce viewer HTTPS at the edge, forward the public Host header when the origin uses a different DNS name, and map a trusted forwarded-proto signal to $_SERVER['HTTPS'] before WordPress loads. URL cleanup for old content and edge-cache purges stay as separate follow-up tasks.

Steps to serve WordPress behind CloudFront over HTTPS:

  1. Set the public WordPress URL to the final HTTPS hostname.
    <?php
    define( 'WP_HOME', 'https://www.example.com' );
    define( 'WP_SITEURL', 'https://www.example.com' );

    If /wp-config.php/ already defines WP_HOME or WP_SITEURL, update the constants there; otherwise update the stored site URLs separately so WordPress stops generating the old origin hostname or plain HTTP links.

  2. Set the CloudFront cache behavior Viewer protocol policy to Redirect HTTP to HTTPS or HTTPS Only.

    Redirect HTTP to HTTPS is the usual choice because legacy HTTP requests are upgraded at the edge before the request reaches WordPress.

  3. Set the CloudFront origin Origin protocol policy to the protocol the origin actually supports, and prefer HTTPS Only when the origin has a valid certificate.

    Match Viewer is safe only when the behavior already enforces viewer HTTPS, because CloudFront forwards the viewer protocol choice to the origin.

    When CloudFront connects to a custom origin over HTTPS, the origin certificate must match the origin domain name or the forwarded Host header, or CloudFront can return 502 Bad Gateway.

  4. Forward the public Host header to the origin when the CloudFront origin domain is different from the hostname visitors use.

    CloudFront always sends a Host header, but the default value is the origin domain name. Attach an origin request policy that includes the viewer Host header so WordPress, the web server, and any origin-side redirects stay aligned to www.example.com instead of an internal load balancer or origin hostname.

  5. Pass a trusted scheme header from CloudFront to the origin.

    If the behavior already redirects or restricts viewers to HTTPS, adding an origin custom header such as X-Forwarded-Proto: https is the simplest option because CloudFront overwrites the value before it sends the origin request.

    If the same origin must handle both HTTP and HTTPS viewer behaviors, forward CloudFront-Forwarded-Proto in an origin request policy instead of hard-coding https.

  6. Map the trusted forwarded-proto header to $_SERVER['HTTPS'] before the line that says /* That's all, stop editing! */ in /wp-config.php/.
    <?php
    if (
        ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && strpos( $_SERVER['HTTP_X_FORWARDED_PROTO'], 'https' ) !== false ) ||
        ( isset( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'] ) && strpos( $_SERVER['HTTP_CLOUDFRONT_FORWARDED_PROTO'], 'https' ) !== false )
    ) {
        $_SERVER['HTTPS'] = 'on';
    }
    
    define( 'FORCE_SSL_ADMIN', true );

    The WordPress is_ssl() guidance still relies on setting $_SERVER['HTTPS'] when a trusted reverse proxy or load balancer terminates TLS before PHP sees the request.

    Trust forwarded headers only when the origin is reachable exclusively from CloudFront or another controlled proxy. A directly reachable origin must not accept client-supplied forwarded-proto headers.

  7. Verify that HTTP upgrades to HTTPS at CloudFront and that the WordPress admin flow stays on the public HTTPS hostname.
    $ curl -I http://www.example.com/
    HTTP/1.1 301 Moved Permanently
    Location: https://www.example.com/
    
    $ curl -I https://www.example.com/wp-admin/
    HTTP/2 302
    location: https://www.example.com/wp-login.php?redirect_to=https%3A%2F%2Fwww.example.com%2Fwp-admin%2F&reauth=1
    server: CloudFront

    A redirect back to http://, to the origin hostname, or to a mixed-scheme wp-admin URL means the public URL, forwarded Host header, or trusted scheme mapping is still misaligned.

    If CloudFront keeps serving an old redirect after the origin-side fix, invalidate the affected paths or wait for the cached response to expire.