I use Nginx > Varnish > Apache, php-fpm in Centos WebPanel.
ERR_TOO_MANY_REDIRECTS appears for the Wordpress homepage only and it goes away and then comes back on my site. This periodical behavior gave the clue that it is a cache-related problem.

Status 301 Moved Permanently
Server nginx/1.16.1
Date Mon, 24 Feb 2020 15:46:29 GMT
Content-Type text/html; charset=iso-8859-1
Content-Length 230
Connection keep-alive
Keep-Alive timeout=60
Location https://thinkbalm.com/
X-Varnish 98379 131369
Age 13
Via 1.1 varnish (Varnish/5.2)
X-Cache HIT from Backend

Setting the domain's configuration to Nginx > Apache, thereby taking out Varnish solves the problem, but then I lose Varnish cache. Therefore I did a lot of searching and the problem seems to be the following:

Varnish and SSL - WordPress Behind an HTTPS Terminating Proxy

Unfortunately, Varnish does not support SSL. So we need to terminate the SSL connection and speak plain HTTP with Varnish and your WordPress site.

Not only does Varnish not support SSL, it is also unaware of the SSL termination and just uses the hostname and the URL of the request as an identifier.

We trigger a problem: forcing HTTPS redirects on an application that is not aware what the initial request protocol, can cause ERR_TOO_MANY_REDIRECTS errors in your browser.

This happens when the HTTP version of a page is stored in cache. The output is nothing more than a 301 redirect to the HTTPS version. But because Varnish and WordPress are unaware of SSL termination, you’ll end up in a redirection loop until the browser throws this error.

How can we solve this?

I tried adding this to the wp-config file:

 if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'){
   $_SERVER['HTTPS'] = 'on';
   $_SERVER['SERVER_PORT'] = 443;

I also tried to add this to .htaccess:

SetEnvIf X-Forwarded-Proto "https" HTTPS=on
Header append Vary: X-Forwarded-Proto

<IfModule mod_rewrite.c>
  RewriteEngine on
  RewriteCond %{HTTPS} !=on
  RewriteCond %{HTTP:X-Forwarded-Proto} !https [NC]
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

None of these resolved the situation.

Any ideas?

  • Well the whole debate about SSL encryption support was intentionally left out of Varnish by the inventor of the program. He does give a hint on what todo: varnish-cache.org/docs/trunk/phk/ssl_again.html. Mind you PHK does take a security approach that makes the rest of us look like amateurs no matter how experienced we are. :-) – Lasse Michael Mølgaard Feb 25 '20 at 10:56

The entire solution, which I wrote a blog post about, depends on the presence of the X-Forwarded-Proto header.

  • Without it, the HTTPS environment variable cannot be set in Apache.
  • Without it, Varnish cannot perform the cache variation

My initial assumption is that this header is not properly set. But there's an easy way to find out:

Please send me the output of the following Varnish command:

varnishlog -g request -q "ReqUrl eq '/'"`

I'm assuming this happens on the homepage, so the command filters for requests on the homepage.

Please also confirm if you have a custom sub vcl_hash configuration that influences the way cache variations are done.

  • Thanks. Uploaded here drive.google.com/file/d/1hGDvnTUxo6jM44GxQGAkdh6CcipjJZII/… – Peter Nyiri Feb 27 '20 at 2:54
  • The output of your varnishlog output states that the incoming request is done using HTTP version 1.0. Maybe that's the reason why Varnish is not behaving as expected. Please use HTTP 1.1 instead. You can set the proxy command in Nginx with the following config: nginx.org/en/docs/http/… – Thijs Feryn Feb 28 '20 at 13:17
  • I added http 1.1 to the domain conf file, but no change. An additional point is that the log has 2 more domains that also has http 1.0 incoming request, but the error doesn't come up (travelhunter and ajandeksziget) I found a common point on these two - they both have Hummingbird cache plugin set up. Seems like HB gets the correct response while even wp-rocket doesn't. – Peter Nyiri Feb 28 '20 at 18:58
  • Based on the output I'm seeing for the requests that result in a MISS, there's actually no Vary: X-Forwarded-Proto being returned. For ** << BeReq >> 98921, this is the Vary header output: BerespHeader Vary: Accept-Encoding,Cookie Please make sure Vary: X-Forwarded-Proto is being returned by the backend, and you'll probably be fine. – Thijs Feryn Feb 28 '20 at 21:02
  • Thanks, I found a code that seems to have resolved the problem by adding it to varnish vcl: saadhost.com/solved-err_too_many_redirects-varnishnginx – Peter Nyiri Mar 1 '20 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.