monolithic kernel

Varnishで複数のバーチャルホストを運用する

Varnish1つで複数のサイトを動かそうとしたとき、普通に記述していくと複数サイトの設定が混在する読みづらいファイルになってしまいます。ここでは、設定をサイトごとに分離して分かりやすく記述する方法を紹介します。

実現方法

VCLでは同じ名前のサブルーチンが複数定義されている場合、コード中で出現した順で連結されるという機能があります。これとincludeを利用して、複数サイトの設定を分離します。

設定

sitesディレクトリにサイトごとの設定ファイルを用意しておき、default.vclで読み込みます。各サイト用の設定ファイルでは、req.http.hostの値を見て処理を行うようにします。

/etc/varnish
├── default.vcl
├── secret
└── sites
    ├── app-a.vcl
    ├── app-b.vcl
    └── purge.vcl

default.vcl

include "/etc/varnish/sites/app-a.vcl";
include "/etc/varnish/sites/app-b.vcl";
include "/etc/varnish/sites/purge.vcl";

app-a.vcl

backend app_a {
    .host = "127.0.0.1";
    .port = "9000";
    .connect_timeout = 30s;
}

sub vcl_recv {
    if (req.http.host == "app-a.com") {
        set req.backend = app_a;
        return (lookup);
    }
}

sub vcl_fetch {
    if (req.http.host == "app-a.com") {
        set beresp.ttl = 1h;
    }
}

app-b.vcl

backend app_b {
    .host = "127.0.0.1";
    .port = "9100";
    .connect_timeout = 30s;
}

sub vcl_recv {
    if (req.http.host == "app-b.com") {
        set req.backend = app_b;
        return (lookup);
    }
}

sub vcl_hash {
    if (req.http.host == "app-b.com") {
        set req.hash += req.url;
        set req.hash += req.http.X-PJAX;
    }
}

sub vcl_fetch {
    if (req.http.host == "app-b.com") {
        set beresp.ttl = 30m;
    }
}

purge.vcl

acl purge {
    "localhost";
}

sub vcl_recv {
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        purge("req.http.host == " req.http.host " && req.url ~ " req.url);
        error 200 "Purged.";
    }
}