Solved: ERR_TOO_MANY_REDIRECTS Varnish+NGINX

ERR_TOO_MANY_REDIRECTS

The ERR_TOO_MANY_REDIRECTS with Varnish + NGINX appears for the wordpress homepage only and it goes away and then comes back on my site, Thinkbalm. 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

I am using Nginx > Varnish > Apache, php-fpm. Setting the domain’s configuration to Nginx > Apache, thereby taking out Varnish solves the problem, but then you lose your 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

Varnish is a reverse caching proxy server that speeds up the performance of your website. It is commonly used in conjunction with WordPress.

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.

I have found a workaround for this:

sub vcl_backend_response {

#Fix a strange problem: HTTP 301 redirects to the same page sometimes go in$
if (beresp.http.Location == “http://” + bereq.http.host + bereq.url) {
if (bereq.retries > 2) {
unset beresp.http.Location;
#set beresp.http.X-Restarts = bereq.retries;
} else {
return (retry);
}
}

}

I put this into the following config file:

etc/varnish/conf.d/vhosts/yoursite.com.conf

or

etc/varnish/default.vcl