Etcpasswd

Nginx + Varnish + Symfony2 Because caching is important!

This site is using Varnish now to selectively cache elements using Edge Side includes. Quite easy actually to do in symfony. You just have to enable it.

Varnish Configuration:

backend default {
    .host = "127.0.0.1";
    .port = "8080";
}
acl purge {
    "localhost";
}
sub vcl_recv {
    if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        return(lookup);
    }

    set req.http.Surrogate-Capability = "abc=ESI/1.0";
    unset req.http.Accept-Encoding;

    ## Check if we are having cookies which we might need to strip
    if (req.http.Cookie) {
        set req.http.Cookie = ";" req.http.Cookie;
        set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
        set req.http.Cookie = regsuball(req.http.Cookie, ";(PHPSESSID)=", "; \1=");
        set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
        set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");

        if (req.url ~ "\.(png|gif|jpg|css|js)$") {
            remove req.http.Cookie;
        }

        if (req.http.Cookie == "") {
            remove req.http.Cookie;
        }

        if (req.http.x-is-anonymous) {
            remove req.http.Cookie;
        }
    }

}
sub vcl_hit {
    if(req.request == "PURGE") {
        set obj.ttl = 0s;
        error 200 "Purged.";
    }
}
sub vcl_miss {
    if(req.request == "PURGE") {
        error 404 "Not in cache.";
    }
}
sub vcl_fetch {
    if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
        unset beresp.http.Surrogate-Control;
        esi;
    }
    if (beresp.http.x-is-anonymous) {
        remove req.http.Cookie;
        unset beresp.http.set-cookie;
    }

    if (beresp.http.cache-control ~ "no-cache") {
        set beresp.ttl = 0s;
    }
    if (req.url ~ "\.(png|gif|jpg|css|js)$") {
        unset beresp.http.set-cookie;
        set beresp.ttl = 1h;
    }
}

NginX config:

map $server_port $ssl_enabled {
    default off;
    443 on;
}
server {
    listen 8080;

    root /var/www/$host/current/web;
    index app.php;

    location / {
        try_files /maintenance.html $uri $uri/ /app.php?$args;
    }

    location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
        try_files $uri /app.php;
        expires max;
        break;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param HTTPS $ssl_enabled;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

The only caveat is that the 2.1 version of varnish cannot handle gzip compression correctly. This can be solved though by adding a small nginx server in front of it which handles the compression for you:

upstream cache {
    server localhost:6081; # Varnish
    server localhost:8080 backup; # Symfony app (in case varnish fails)
}
server {
    listen 80;

    location / {
        proxy_pass http://cache;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        gzip on;
    }

}