WordPress, Varnish, nginx: The SSL https detection problem

I have a certain setup with a Varnish5 caching reverse proxy, with nginx to terminate SSL connections.

The problem with this setup is that wordpress can’t detect https, hence, it can not enforce it, nor will it link the CSS accordingly etc…, and if your blog’s address starts with https, you have a problem.

there is more than one solution that i will enumerate here, I chose to force all connections to come through https (The first), but there are others, the one i will present here (Which i did not use) resolves the problem and allows wordpress to detect whether we are on a secure connection or not.

And even though this post-article talks about wordpress, everything here can apply to any PHP application (Or even other applications written in different programming languages)

1- Enforce https for the whole website

The simplest way to solve the problem (Which i chose) is to redirect all traffic to https.

in the varnish script, implement the following

in the sub vcl_recv, implement the following

if (req.http.host ~ "^(www\.)?example\.com$") 
{
	if (req.http.host ~ "^(?i)example.com" || req.http.X-Forwarded-Proto !~ "(?i)https") {
		return (synth(750, ""));
	}
}

Now, the following section is the sub vcl_synth

sub vcl_synth {
    if (resp.status == 750) {
        set resp.status = 301;
        set resp.http.Location = "https://www.example.com" + req.url;
        return(deliver);
    }
}

Once the above is in place in the varnish script, You will need to tell wordpress that it’s all HTTPS (SSL)

We do that in the config file, the only file we know that does not change when we update

define('FORCE_SSL_ADMIN', true);
$_SERVER['HTTPS']='on';

Now, the above should do it if you don’t mind that your website only works in https, if you do want http to remain an option, then here is another solution

Start by creating a phpinfo() page to check whether you have the $_SERVER[‘HTTP_X_FORWARDED_PROTO‘] variable , if you do, your work is partially done, but you need to mind too things

the varnish server needs to only cache the https copy (because most browsers won’t allow mixed content these days, and if the css is linked to as http, it won’t display correctly), you can do that easily with something like the following in the vcl_hash area

if (req.http.X-Forwarded-Proto) {
        hash_data(req.http.X-Forwarded-Proto);
    }

And then, also in the wp-config file, add the following (probably almost anywhere)

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
        $_SERVER['HTTPS']='on';

Leave a Reply

Your email address will not be published. Required fields are marked *