Configure multiple sites with Varnish
We have a server which needs to serve multiple domains though varnish e.g. example1.com, example2.com and example3.com
Our current .vcl file looks like this:
sub vcl_recv {
set req.http.Host = "example1.com";
lookup;
}
How do I set the correct req.http.Host for the correct incoming request?
You can support multiple frontend domains this way:
backend example1 {
.host = "backend.example1.com";
.port = "8080";
}
backend example2 {
.host = "backend.example2.com";
.port = "8080";
}
sub vcl_recv {
if (req.http.host == "example1.com") {
#You will need the following line only if your backend has multiple virtual host names
set req.http.host = "backend.example1.com";
set req.backend = example1;
return (lookup);
}
if (req.http.host == "example2.com") {
#You will need the following line only if your backend has multiple virtual host names
set req.http.host = "backend.example2.com";
set req.backend = example2;
return (lookup);
}
}
I'm using setup similar to Cristian's, but in if clauses I match req.http.host against regular expression:
#for www.example.com or example.com
if (req.http.host ~ "^(www\.)?example\.com$") {
set req.backend = example_com;
return (lookup);
}
#with any subdomain support
if (req.http.host ~ "^(.*\.)?example2\.com$") {
set req.backend = example2_com;
return (lookup);
}
Don't forget to set backends appropriately!
unable to add comment so here we go
slight modification for varnish 4
#for www.example.com or example.com
if (req.http.host ~ "^(www\.)?example\.com$") {
set req.backend_hint = example_com;
return (hash);
}
#with any subdomain support
if (req.http.host ~ "^(.*\.)?example2\.com$") {
set req.backend_hint = example2_com;
return (hash);
}
replace backend with backend_hint
I'd like to add a little more detail to both Cristian Vidmar and msurovcak's posts
The "(req.http.host == "example1.com") " Pattern:
We have used the pattern described to host tens to hundreds of sites per server.
You can continue with site specific custom rules throughout your entire config (vcl_fetch/vcl_backend_response, vcl_hash etc) using the
if (req.http.host == "example1.com") {
example wherever needed.
Combine this with a templating engine to allow customer specific configurations to be managed via individual files that contain their own logic (all wrapped with their site specific if blocks to isolate the code).
You then include each individual site block into the default.vcl using:
include "/etc/varnish/www.example1.com.vcl";
An optional enhancement to totally split backends:
If you are hosting totally different websites then split backends (and split cache) is a good way to go.
If the sites are similar (same codebase/js/css/images) it can be interesting to run a resources domain eg. resources.example.com that all sites use.
You can then have a single cache (and very high hit rate) across each of the common elements of multiple sites and still maintain differences on the individual www sites.
Another alternative to using split back ends:
Another option is to split out the Varnish instances via containers. Each then becomes it's own isolated world that is managed (and lives and dies) individually. This can be a good safety option and the overhead of multiple processes is minimal on modern infrastructure.
Some advantages of this is that you can then support different versions of Varnish and different Varnish startup parameters per instance.
This can be great for individual logging, leveraging different ESI modes per instance and individual memory/tuning configuration settings.
We do this at www.section.io and it also gives us the ability to run different containers in different geographical locations or the same containers in different locations to get as close as possible to geographically dispersed user bases.