@@ -7,27 +7,91 @@ How to Use Varnish to Speed up my Website
7
7
Because Symfony's cache uses the standard HTTP cache headers, the
8
8
:ref: `symfony-gateway-cache ` can easily be replaced with any other reverse
9
9
proxy. `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 >`.
11
11
12
- Trusting Reverse Proxies
13
- ------------------------
12
+ .. index ::
13
+ single: Varnish; configuration
14
+
15
+ Make Symfony Trust the Reverse Proxy
16
+ ------------------------------------
14
17
15
18
For ESI to work correctly and for the :ref: `X-FORWARDED <varnish-x-forwarded-headers >`
16
19
headers to be used, you need to configure Varnish as a
17
20
:doc: `trusted proxy </cookbook/request/load_balancer_reverse_proxy >`.
18
21
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.
21
30
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:
24
37
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.
31
95
32
96
.. note ::
33
97
@@ -58,22 +122,12 @@ Symfony adds automatically:
58
122
59
123
.. code-block :: varnish4
60
124
61
- /* (https://www.varnish-cache.org/docs/4.0/whats-new/upgrading.html#req-not-available-in-vcl-backend-response) */
62
125
sub vcl_backend_response {
63
126
// Check for ESI acknowledgement and remove Surrogate-Control header
64
127
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
65
128
unset beresp.http.Surrogate-Control;
66
129
set beresp.do_esi = true;
67
130
}
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
- }
77
131
}
78
132
79
133
.. code-block :: varnish3
@@ -84,38 +138,13 @@ Symfony adds automatically:
84
138
unset beresp.http.Surrogate-Control;
85
139
set beresp.do_esi = true;
86
140
}
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
- }
95
141
}
96
142
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 ::
115
144
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 .
119
148
120
149
.. index ::
121
150
single: Varnish; Invalidation
@@ -134,139 +163,8 @@ proxy before it has expired, it adds complexity to your caching setup.
134
163
invalidation by helping you to organize your caching and
135
164
invalidation setup.
136
165
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.
270
168
271
169
.. _`Varnish` : https://www.varnish-cache.org
272
170
.. _`Edge Architecture` : http://www.w3.org/TR/edge-arch
0 commit comments