My Magento shop using Varnish is not caching pages over SSL

in CachingTroubleshooting

We have seen a few cases where Magento 1 in combination with Turpentine does not cache pages served over SSL.
We have not yet been able to find the actual cause, but all cases had in common that the HTTP_X_FORWARDED_FOR header was not set in the PHP environment, causing Magento to redirect all traffic back to HTTP instead of serving the page over SSL.

To resolve this, verify if the HTTP_X_FORWARDED_FOR header is correctly set.

Check if the HTTP_X_FORWARDED_FOR using a phpinfo page

To do this, create a PHP script as info.php in /data/web/public with the following content:

    header('Pragma: no-cache');
    header('Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate, proxy-revalidate');

Now visit the phpinfo script by visiting and scroll all the way down to the section PHP Variables.
Now check if the $_SERVER['HTTP_X_FORWARDED_FOR'] variable is set in your PHP environment.

Check the HTTP_X_FORWARDED_FOR header using varnishlog

With Varnish a very useful utility is shipped called varnishlog. This tool can log all debug and request information Varnish is producing, making it the perfect tool to debug header issues and Varnish errors.

To check for the correct header, use the following command:

varnishlog | grep X-Forwarded

This will produce some output showing whether the X-Forwarded-For is set as a BereqHeader (Bereq is the name for Backend request, meaning the request containing the header is send to the PHP-FPM instance serving Magento):

app@12345-support-magweb-do:~$ varnishlog  | grep X-Forwarded
-   BereqHeader    X-Forwarded-Proto: https
-   BereqHeader    X-Forwarded-Port: 443
-   BereqHeader    X-Forwarded-For:,,

Resolving this issue

Magento uses the X-Forwarded-For header to determine whether a redirect to SSL is needed or if the SSL offload has already been done on the proxy server in front of Magento.
If the header is not set, Magento will assume SSL offloading has already been done, effectively serving the page over HTTP instead of HTTPS.

To resolve this, change the base URL settings. This sounds odd, but in some way this resolves all the cases we’ve seen so far.