@@ -7,27 +7,91 @@ How to Use Varnish to Speed up my Website
77Because Symfony's cache uses the standard HTTP cache headers, the
88:ref: `symfony-gateway-cache ` can easily be replaced with any other reverse
99proxy. `Varnish `_ is a powerful, open-source, HTTP accelerator capable of serving
10- cached content quickly and including support for :ref: `Edge Side Includes <edge-side-includes >`.
10+ cached content fast and including support for :ref: `Edge Side Includes <edge-side-includes >`.
1111
12- Trusting Reverse Proxies
13- ------------------------
12+ .. index ::
13+ single: Varnish; configuration
14+
15+ Make Symfony Trust the Reverse Proxy
16+ ------------------------------------
1417
1518For ESI to work correctly and for the :ref: `X-FORWARDED <varnish-x-forwarded-headers >`
1619headers to be used, you need to configure Varnish as a
1720:doc: `trusted proxy </cookbook/request/load_balancer_reverse_proxy >`.
1821
19- .. index ::
20- single: Varnish; configuration
22+ .. _varnish-x-forwarded-headers :
23+
24+ Routing and X-FORWARDED Headers
25+ -------------------------------
26+
27+ To ensure that the Symfony Router generates URLs correctly with Varnish,
28+ a ``X-Forwarded-Port `` header must be present for Symfony to use the
29+ correct port number.
2130
22- Configuration
23- -------------
31+ This port depends on your setup. Lets say that external connections come in
32+ on the default HTTP port 80. For HTTPS connections, there is another proxy
33+ (as Varnish does not do HTTPS itself) on the default HTTPS port 443 that
34+ handles the SSL termination and forwards the requests as HTTP requests to
35+ Varnish with a ``X-Forwarded-Proto `` header. In this case, you need to add
36+ the following configuration snippet:
2437
25- As seen previously, Symfony is smart enough to detect whether it talks to a
26- reverse proxy that understands ESI or not. It works out of the box when you
27- use the Symfony reverse proxy, but you need a special configuration to make
28- it work with Varnish. Thankfully, Symfony relies on yet another standard
29- written by Akamai (`Edge Architecture `_), so the configuration tips in this
30- chapter can be useful even if you don't use Symfony.
38+ .. code-block :: varnish4
39+
40+ sub vcl_recv {
41+ if (req.http.X-Forwarded-Proto == "https" ) {
42+ set req.http.X-Forwarded-Port = "443";
43+ } else {
44+ set req.http.X-Forwarded-Port = "80";
45+ }
46+ }
47+
48+ .. note ::
49+
50+ Remember to configure :ref: `framework.trusted_proxies <reference-framework-trusted-proxies >`
51+ in the Symfony configuration so that Varnish is seen as a trusted proxy
52+ and the ``X-Forwarded-* `` headers are used.
53+
54+ Varnish automatically forwards the IP as ``X-Forwarded-For `` and leaves
55+ the ``X-Forwarded-Proto `` header in the request. If you do not configure
56+ Varnish as trusted proxy, Symfony will see all requests as coming through
57+ insecure HTTP connections from the Varnish host instead of the real client.
58+
59+ If the ``X-Forwarded-Port `` header is not set correctly, Symfony will append
60+ the port where the PHP application is running when generating absolute URLs,
61+ e.g. ``http://example.com:8080/my/path ``.
62+
63+ Ensure Consistent Caching Behaviour
64+ -----------------------------------
65+
66+ Varnish uses the cache headers sent by your application to determine how
67+ to cache content. However, versions prior to Varnish 4 did not respect
68+ ``Cache-Control: no-cache ``. To ensure consistent behaviour, use the following
69+ configuration if you are still using Varnish 3:
70+
71+ .. configuration-block ::
72+
73+ .. code-block :: varnish3
74+
75+ sub vcl_fetch {
76+ /* By default, Varnish3 ignores Cache-Control: no-cache and private
77+ https://www.varnish-cache.org/docs/3.0/tutorial/increasing_your_hitrate.html#cache-control
78+ */
79+ if (beresp.http.Cache-Control ~ "no-cache" ||
80+ beresp.http.Cache-Control ~ "private"
81+ ) {
82+ return (hit_for_pass);
83+ }
84+ }
85+
86+ Enable Edge Side Includes (ESI)
87+ -------------------------------
88+
89+ As explained in the :ref: `Edge Side Includes section<edge-side-includes> `,
90+ Symfony detects whether it talks to a reverse proxy that understands ESI or
91+ not. When you use the Symfony reverse proxy, you don't need to do anything.
92+ But to make Varnish instead of Symfony resolve the ESI tags, you need some
93+ configuration in Varnish. Symfony uses the ``Surrogate-Capability `` header
94+ from the `Edge Architecture `_ described by Akamai.
3195
3296.. note ::
3397
@@ -58,22 +122,12 @@ Symfony adds automatically:
58122
59123 .. code-block :: varnish4
60124
61- /* (https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html#req-not-available-in-vcl-backend-response) */
62125 sub vcl_backend_response {
63126 // Check for ESI acknowledgement and remove Surrogate-Control header
64127 if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
65128 unset beresp.http.Surrogate-Control;
66129 set beresp.do_esi = true;
67130 }
68- /* By default Varnish ignores Pragma: nocache
69- (https://www.varnish-cache.org/docs/4.0/users-guide/increasing-your-hitrate.html#cache-control)
70- so in order avoid caching it has to be done explicitly */
71- if (beresp.http.Pragma ~ "no-cache") {
72- // https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html#hit-for-pass-objects-are-created-using-beresp-uncacheable
73- set beresp.uncacheable = true;
74- set beresp.ttl = 120s;
75- return (deliver);
76- }
77131 }
78132
79133 .. code-block :: varnish3
@@ -84,38 +138,13 @@ Symfony adds automatically:
84138 unset beresp.http.Surrogate-Control;
85139 set beresp.do_esi = true;
86140 }
87- /* By default Varnish ignores Cache-Control: nocache
88- (https://www.varnish-cache.org/docs/3.0/tutorial/increasing_your_hitrate.html#cache-control),
89- so in order avoid caching it has to be done explicitly */
90- if (beresp.http.Pragma ~ "no-cache" ||
91- beresp.http.Cache-Control ~ "no-cache" ||
92- beresp.http.Cache-Control ~ "private") {
93- return (hit_for_pass);
94- }
95141 }
96142
97- .. code-block :: varnish2
98-
99- sub vcl_fetch {
100- // Check for ESI acknowledgement and remove Surrogate-Control header
101- if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
102- unset beresp.http.Surrogate-Control;
103- esi;
104- }
105- /* By default Varnish ignores Cache-Control: nocache
106- so in order avoid caching it has to be done explicitly */
107- if (beresp.http.Pragma ~ "no-cache" ||
108- beresp.http.Cache-Control ~ "no-cache" ||
109- beresp.http.Cache-Control ~ "private") {
110- return (hit_for_pass);
111- }
112- }
113-
114- .. caution ::
143+ .. tip ::
115144
116- Compression with ESI was not supported in Varnish until version 3.0
117- (read ` GZIP and Varnish `_). If you're not using Varnish 3.0, put a web
118- server in front of Varnish to perform the compression .
145+ If you followed the advice about ensuring a consistent caching
146+ behaviour, those vcl functions already exist. Just append the code
147+ to the end of the function, they won't interfere with each other .
119148
120149.. index ::
121150 single: Varnish; Invalidation
@@ -134,139 +163,8 @@ proxy before it has expired, it adds complexity to your caching setup.
134163 invalidation by helping you to organize your caching and
135164 invalidation setup.
136165
137- Varnish can be configured to accept a special HTTP ``PURGE `` method
138- that will invalidate the cache for a given resource:
139-
140- .. code-block :: varnish4
141-
142- /*
143- Connect to the backend server
144- on the local machine on port 8080
145- */
146- backend default {
147- .host = "127.0.0.1";
148- .port = "8080";
149- }
150-
151- sub vcl_recv {
152- /*
153- Varnish default behavior doesn't support PURGE.
154- Match the PURGE request and immediately do a cache lookup,
155- otherwise Varnish will directly pipe the request to the backend
156- and bypass the cache
157- */
158- if (req.request == "PURGE") {
159- return(lookup);
160- }
161- }
162-
163- sub vcl_hit {
164- // Match PURGE request
165- if (req.request == "PURGE") {
166- // Force object expiration for Varnish < 3.0
167- set obj.ttl = 0s;
168- // Do an actual purge for Varnish >= 3.0
169- // purge;
170- error 200 "Purged";
171- }
172- }
173-
174- sub vcl_miss {
175- /*
176- Match the PURGE request and
177- indicate the request wasn't stored in cache.
178- */
179- if (req.request == "PURGE") {
180- error 404 "Not purged";
181- }
182- }
183-
184- .. caution ::
185-
186- You must protect the ``PURGE `` HTTP method somehow to avoid random people
187- purging your cached data. You can do this by setting up an access list:
188-
189- .. code-block :: varnish4
190-
191- /*
192- Connect to the backend server
193- on the local machine on port 8080
194- */
195- backend default {
196- .host = "127.0.0.1";
197- .port = "8080";
198- }
199-
200- // ACL's can contain IP's, subnets and hostnames
201- acl purge {
202- "localhost";
203- "192.168.55.0"/24;
204- }
205-
206- sub vcl_recv {
207- // Match PURGE request to avoid cache bypassing
208- if (req.request == "PURGE") {
209- // Match client IP to the ACL
210- if (!client.ip ~ purge) {
211- // Deny access
212- error 405 "Not allowed.";
213- }
214- // Perform a cache lookup
215- return(lookup);
216- }
217- }
218-
219- sub vcl_hit {
220- // Match PURGE request
221- if (req.request == "PURGE") {
222- // Force object expiration for Varnish < 3.0
223- set obj.ttl = 0s;
224- // Do an actual purge for Varnish >= 3.0
225- // purge;
226- error 200 "Purged";
227- }
228- }
229-
230- sub vcl_miss {
231- // Match PURGE request
232- if (req.request == "PURGE") {
233- // Indicate that the object isn't stored in cache
234- error 404 "Not purged";
235- }
236- }
237-
238- .. _varnish-x-forwarded-headers :
239-
240- Routing and X-FORWARDED Headers
241- -------------------------------
242-
243- To ensure that the Symfony Router generates URLs correctly with Varnish,
244- proper ```X-Forwarded` `` headers must be added so that Symfony is aware of
245- the original port number of the request. Exactly how this is done depends
246- on your setup. As a simple example, Varnish and your web server are on the
247- same machine and that Varnish is listening on one port (e.g. 80) and Apache
248- on another (e.g. 8080). In this situation, Varnish should add the ``X-Forwarded-Port ``
249- header so that the Symfony application knows that the original port number
250- is 80 and not 8080.
251-
252- If this header weren't set properly, Symfony may append ``8080 `` when generating
253- absolute URLs:
254-
255- .. code-block :: varnish4
256-
257- sub vcl_recv {
258- if (req.http.X-Forwarded-Proto == "https" ) {
259- set req.http.X-Forwarded-Port = "443";
260- } else {
261- set req.http.X-Forwarded-Port = "80";
262- }
263- }
264-
265- .. note ::
266-
267- Remember to configure :ref: `framework.trusted_proxies <reference-framework-trusted-proxies >`
268- in the Symfony configuration so that Varnish is seen as a trusted proxy
269- and the ``X-Forwarded- `` headers are used.
166+ The documentation of the `FOSHttpCacheBundle `_ explains how to configure
167+ Varnish and other reverse proxies for cache invalidation.
270168
271169.. _`Varnish` : https://www.varnish-cache.org
272170.. _`Edge Architecture` : http://www.w3.org/TR/edge-arch
0 commit comments