Nginx – Keep the host name requested by the client to pass to remote backend when using Varnish cache and proxy pass

httpnginxPROXYreverse-proxyvarnish

I am having some trouble configuring Varnish and the online documentation is not very clear (for me at least). I currently have Varnish cache setup on a Ubuntu server. I tested varnish with a local Nginx on the same server and it worked fine. What i want to do is use Varnish as a cache and reverse proxy for a remote web server configured with Nginx. I need to keep the host name requested by the client and pass that to the remote Nginx web server. This can be done in Nginx using the proxy_set_header Host, and Apache by using ProxyPreserveHost On. The problem is that i have many different virtual hosts on my remote Nginx and the DNS of the server is not configured with any of them. They are all different so i need to make sure that the host requested from the client is passed through. I apologise if this is not clear but i am brand new to Varnish and it is nothing like i am used to with Apache or Nginx. Any help would be greatly appreciated.

Here is my default.vcl:

vcl 4.0;

# Default backend definition. Set this to point to your content 
server.
backend default {
    .host = "dns.of.remote.nginx.server";
    .port = "80";
    .probe = {
        .url = "/";
        .timeout = 30s;
        .threshold = 8;
     }
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you 
    don't need,
    # rewriting the request, etc.
    unset req.http.Cookie;

    set req.http.x-host = req.http.host;
    set req.http.x-url = req.url;
    set req.url = req.url;
}

sub vcl_backend_response {
    # Happens after we have read the response headers from the 
    backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie 
headers
    # and other mistakes your backend does.
}

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to 
    send the
    # response to the client.
    #
    # You can do accounting or modifying the final object here.
}

Best Answer

First of all, you typically should never specify a DNS hostname in Varnish backend definition. It is resolved only during startup and never updated. Specify IP of remove Nginx server instead.

Second, what you're asking is already the default behaviour of Varnish. It is a transparent caching HTTP proxy, and as such - it will pass through whatever Host header is sent via HTTP by clients.