A redirect loop means every response says 'go somewhere else' until the browser gives up. Nine times out of ten it's HTTP→HTTPS misconfiguration in front of an origin that can't see the original scheme.
The proxy connects to the origin over HTTP; the origin 301s back to https; the proxy requests again over HTTP — infinite loop. The fix is a header (X-Forwarded-Proto) the origin trusts, or proxy-level SSL to origin.
Server A redirects to the name that Server B redirects back from. Trace with curl -IL and read each Location hop.
An old 301 cached at the edge/CDN keeps applying after you fixed the config. Purge the CDN and check for stale browser cache.
curl -sIL http://example.com/ | grep -iE 'HTTP/|location'
# map $http_x_forwarded_proto $forwarded_https { default off; https on; }
# then: if ($forwarded_https = off) { return 301 https://$host$request_uri; }
server { listen 80; server_name example.com; return 301 https://$host$request_uri; } # no 301 inside the 443 server block
# Cloudflare 'Flexible' SSL + origin HTTPS redirect = loop. Use 'Full (strict)' with a valid origin cert.
curl -IL is the single most useful command here — it shows the entire hop chain including which layer bounces first. 301s are cached aggressively by browsers; test with curl or incognito after fixing.
Cloudflare Flexible SSL fetches your origin over plain HTTP. Your origin sees HTTP and redirects to HTTPS, and the loop begins. Switch Cloudflare SSL to Full (strict) and install an origin certificate.
Purge the CDN cache for the URL, and test in a fresh incognito window or with curl. Browser-cached 301s often outlive your patience otherwise.
Our most-documented failures, packaged as ready-to-ship starter kits: Docker, Kubernetes, and Terraform.
Browse the template store →One-time. Yours to modify. Instant download from the NinjaOps template store.