Press "Enter" to skip to content

Redirect HTTP to HTTPS in WordPress running behind a Google HTTP Load Balancer

We’ve setup a multi-node WordPress installation in Kubernetes running inside the Google Container Engine in the Google Cloud Environment. We’ve also created Google HTTP Load Balancer that routes traffic to our WordPress website. The load balancer is configured to accept requests for both http and https. The only reason why we’re exposing http is to allow people just typing http://our-website.com to be redirected to https instead of just getting an error. This is of course very common and there are even plugins such as Easy HTTPS Redirection that can handle this for you. The problem is that we’re behind a load balancer so these plugins doesn’t work. To understand why let’s see what the Easy HTTPS Redirection actually does. All it does is to provide a convenient way to write the following rules to the .htaccess file in WordPress root directory:

What this does is to check if HTTPS is “off” (i.e. the request is just http) and if so redirect to https instead. This is fine if Apache does SSL termination but since we’re using the Google HTTP Load Balancer it won’t work. The reason is that ALL requests to our WordPress installation will be sent as HTTP from the load balancer and we’ll end up in an infinite redirection cycle. Fortunately Google follows the defacto standard of adding a header called X-Forwarded-Proto that contains the protocol (http or https) used to access the load balancer. Thus we can change our .htaccess file to include this instead:

Now we can access http://our-website.com and be redirect to https . . . for a while! After a minute or so you’ll run into an error page saying that the request timed out. This page is served by the backend service created as a part of creating the Google Load Balancer. The reason we’re seeing this page is that our health check associated with the backend service has failed. But why? The health check makes a call to / (by default) using HTTP and since the backend service is located behind the load balancer no X-Forwarded-Proto header is added to the request. This means that the health check request gets a response that looks like similar to this:

The problem is that the health doesn’t follow redirects and the response must return a 200 OK which means that it will interpret this response as a failure! And soon enough it’ll mark this backend service as failed and the load balancer will not forward any more requests to it (which means that we’ll see the error page described earlier). Your initial reaction might be the same as mine, can’t we just add the X-Forwarded-Proto to our health checker and this way trick Apache that we’re behind a load balancer? Unfortunately Google does not allow you to add a header to the health check so this won’t work. The workaround I came up with instead is to add a query parameter to the path used by the health checker, for example /?healthCheck=true. Now we need to update the .htaccess file to only redirect if X-Forwarded-Proto is not “https” AND the query string does not contain healthCheck=true. This is how it’s done:

And that’s it! This means that we’ll allow the Google health checker to access our page using HTTP but all other requests are redirected to HTTPS.

Conclusion

Even though I managed to get this working in the end I find it quite unfortunate that the Google health checker doesn’t support adding headers. This would have simplified not only this use case but also other cases where (for example) your health check is protected by basic authentication. Now one has to resort to various work arounds to get things working correctly.

One Comment

  1. […] of issues when we were trying to redirect our WordPress instance from http to https as described in this blog. I’ve created an issue for this that has been accepted so hopefully this will be available in […]

Leave a Reply

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