Varnish – redirect to HTTPS with VCL 4.1

Varnish and HTTPS

Why doesn’t Varnish support SSL/TSL? This is a fact and there are many ways to handle this issue. If you want, it can be handled with NginX (as a TSL Terminatoin Proxy), in my opinion, Pound is a very good choice but not the only one. There are well-documended tutorials how to do this but I want to write about another problem witch, in my opinion, is not documented at all. How to redirect all requests to HTTP without an infinite loop?


TSL Termination Proxy + Varnish  + Backend (WWW)

No redirect on backends

There are many methods to send 301 headers from backend. In Apache we have rewrites, in NgineX we simply return 301 or rewrite as well, Lighthttpd, IIS, and others backend servers have it. But there are too deep in this schema. All redirects fail with “Too many redirects” information in a browser.

A quite good answer – redirect in application (or backends)

 * Redirect all requests to HTTPS when HTTP_X_SSL_CIPHER is not set
    header('Cache-Control: no-cache' );//For Varnish
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: https://".$_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"]);

In my case, it wasn’t good, but it can be useful on other issues.

The first problem is how to check that we are behind HTTPS. In my case, there are
$_SERVER['HTTP_X_SSL_CIPHER']  so it was simple. Second problem was still with Varnish.
Without Cache-Control: no-cache header there was still a problem with “Too many redirects”. Becouse http and https request are one for Varnish. When we use this header the problem is not solved. We don’t have problem with “infinite loop” and redirect is working, but only in first request. Second request is with X-Cache:HIT header couse https request was stored in varnish cache engine. Another problem is with other, static requests. The best way is to use VCL, but how to check HTTPS in Varnish? The answer is req.http.X-Forwarded-Proto

All requests to HTTPS – VCL

In Varnish Book  there is an example how to do redirects, but as always, ther are no info about HTTPS (there is no support). When we use VCL we must check it before run, so it can be usefull varnishd -C -f /etc/varnish/default.vcl to check varnish configuration is correct. When everything is OK varnish print out whole configuration, when something is wrong it print error message.

There are two VCL subroutines where we must do some modifications.

sub vcl_recv {
    if ( req.http.X-Forwarded-Proto !~ "(?i)https" ) {
        set req.http.x-Redir-Url = "https://" + + req.url;
        return ( synth( 750 ));


And other part is the vcl_synth  subroutine – it can be new in some configuration. Here we can generate content directly in varnish or do some error messages or redirects.

sub vcl_synth {

    if (resp.status == 750) {
        set resp.status = 301;
        set resp.http.Location = req.http.x-Redir-Url;

I’m sure there are other way to set redirect header in VCL but this method with set req.http.x-Redir-Url in my opinion is universal.

Hope this help U in struggle with Varnish 

Leave a Reply

Your email address will not be published.