Commit | Line | Data |
01b62b15 |
1 | =head1 NAME |
2 | |
3 | Catalyst::Manual::Deployment - Deploying Catalyst |
4 | |
5 | =head1 |
6 | |
7 | =head1 mod_perl |
8 | |
9 | L<Catalyst::Manual::Deployment::Apache::mod_perl> |
10 | |
11 | =head1 FastCGI |
12 | |
13 | =head2 Apache |
14 | |
15 | L<Catalyst::Manual::Deployment::Apache::FastCGI> |
16 | |
17 | |
18 | =head2 mod_perl Deployment |
19 | |
20 | mod_perl is not the best solution for many applications, but we'll list some |
21 | pros and cons so you can decide for yourself. The other (recommended) |
22 | deployment option is FastCGI, for which see below. |
23 | |
24 | =head3 Pros |
25 | |
26 | =head4 Speed |
27 | |
28 | mod_perl is fast and your app will be loaded in memory |
29 | within each Apache process. |
30 | |
31 | =head4 Shared memory for multiple apps |
32 | |
33 | If you need to run several Catalyst apps on the same server, mod_perl will |
34 | share the memory for common modules. |
35 | |
36 | =head3 Cons |
37 | |
38 | =head4 Memory usage |
39 | |
40 | Since your application is fully loaded in memory, every Apache process will |
41 | be rather large. This means a large Apache process will be tied up while |
42 | serving static files, large files, or dealing with slow clients. For this |
43 | reason, it is best to run a two-tiered web architecture with a lightweight |
44 | frontend server passing dynamic requests to a large backend mod_perl |
45 | server. |
46 | |
47 | =head4 Reloading |
48 | |
49 | Any changes made to the core code of your app require a full Apache restart. |
50 | Catalyst does not support Apache::Reload or StatINC. This is another good |
51 | reason to run a frontend web server where you can set up an |
52 | C<ErrorDocument 502> page to report that your app is down for maintenance. |
53 | |
54 | =head4 Cannot run multiple versions of the same app |
55 | |
56 | It is not possible to run two different versions of the same application in |
57 | the same Apache instance because the namespaces will collide. |
58 | |
59 | =head4 Cannot run different versions of libraries. |
60 | |
61 | If you have two different applications which run on the same machine, |
62 | which need two different versions of a library then the only way to do |
63 | this is to have per-vhost perl interpreters (with different library paths). |
64 | This is entirely possible, but nullifies all the memory sharing benefits that |
65 | you get from having multiple applications sharing the same interpreter. |
66 | |
67 | =head4 Setup |
68 | |
69 | Now that we have that out of the way, let's talk about setting up mod_perl |
70 | to run a Catalyst app. |
71 | |
72 | =head4 1. Install Catalyst::Engine::Apache |
73 | |
74 | You should install the latest versions of both Catalyst and |
75 | Catalyst::Engine::Apache. The Apache engines were separated from the |
76 | Catalyst core in version 5.50 to allow for updates to the engine without |
77 | requiring a new Catalyst release. |
78 | |
79 | =head4 2. Install Apache with mod_perl |
80 | |
81 | Both Apache 1.3 and Apache 2 are supported, although Apache 2 is highly |
82 | recommended. With Apache 2, make sure you are using the prefork MPM and not |
83 | the worker MPM. The reason for this is that many Perl modules are not |
84 | thread-safe and may have problems running within the threaded worker |
85 | environment. Catalyst is thread-safe however, so if you know what you're |
86 | doing, you may be able to run using worker. |
87 | |
88 | In Debian, the following commands should get you going. |
89 | |
90 | apt-get install apache2-mpm-prefork |
91 | apt-get install libapache2-mod-perl2 |
92 | |
93 | =head4 3. Configure your application |
94 | |
95 | Every Catalyst application will automagically become a mod_perl handler |
96 | when run within mod_perl. This makes the configuration extremely easy. |
97 | Here is a basic Apache 2 configuration. |
98 | |
99 | PerlSwitches -I/var/www/MyApp/lib |
100 | PerlModule MyApp |
101 | |
102 | <Location /> |
103 | SetHandler modperl |
104 | PerlResponseHandler MyApp |
105 | </Location> |
106 | |
107 | The most important line here is C<PerlModule MyApp>. This causes mod_perl |
108 | to preload your entire application into shared memory, including all of your |
109 | controller, model, and view classes and configuration. If you have -Debug |
110 | mode enabled, you will see the startup output scroll by when you first |
111 | start Apache. |
112 | |
113 | For an example Apache 1.3 configuration, please see the documentation for |
114 | L<Catalyst::Engine::Apache::MP13>. |
115 | |
116 | =head3 Test It |
117 | |
118 | That's it, your app is now a full-fledged mod_perl application! Try it out |
119 | by going to http://your.server.com/. |
120 | |
121 | =head3 Other Options |
122 | |
123 | =head4 Non-root location |
124 | |
125 | You may not always want to run your app at the root of your server or virtual |
126 | host. In this case, it's a simple change to run at any non-root location |
127 | of your choice. |
128 | |
129 | <Location /myapp> |
130 | SetHandler modperl |
131 | PerlResponseHandler MyApp |
132 | </Location> |
133 | |
134 | When running this way, it is best to make use of the C<uri_for> method in |
135 | Catalyst for constructing correct links. |
136 | |
137 | =head4 Static file handling |
138 | |
139 | Static files can be served directly by Apache for a performance boost. |
140 | |
141 | DocumentRoot /var/www/MyApp/root |
142 | <Location /static> |
143 | SetHandler default-handler |
144 | </Location> |
145 | |
146 | This will let all files within root/static be handled directly by Apache. In |
147 | a two-tiered setup, the frontend server should handle static files. |
148 | The configuration to do this on the frontend will vary. |
149 | |
150 | The same is accomplished in lighttpd with the following snippet: |
151 | |
152 | $HTTP["url"] !~ "^/(?:img/|static/|css/|favicon.ico$)" { |
153 | fastcgi.server = ( |
154 | "" => ( |
155 | "MyApp" => ( |
156 | "socket" => "/tmp/myapp.socket", |
157 | "check-local" => "disable", |
158 | ) |
159 | ) |
160 | ) |
161 | } |
162 | |
163 | Which serves everything in the img, static, css directories |
164 | statically, as well as the favicon file. |
165 | |
166 | Note the path of the application needs to be stated explicitly in the |
167 | web server configuration for both these recipes. |
168 | |
169 | =head2 Catalyst on shared hosting |
170 | |
171 | So, you want to put your Catalyst app out there for the whole world to |
172 | see, but you don't want to break the bank. There is an answer - if you |
173 | can get shared hosting with FastCGI and a shell, you can install your |
174 | Catalyst app in a local directory on your shared host. First, run |
175 | |
176 | perl -MCPAN -e shell |
177 | |
178 | and go through the standard CPAN configuration process. Then exit out |
179 | without installing anything. Next, open your .bashrc and add |
180 | |
181 | export PATH=$HOME/local/bin:$HOME/local/script:$PATH |
182 | perlversion=`perl -v | grep 'built for' | awk '{print $4}' | sed -e 's/v//;'` |
183 | export PERL5LIB=$HOME/local/share/perl/$perlversion:$HOME/local/lib/perl/$perlversion:$HOME/local/lib:$PERL5LIB |
184 | |
185 | and log out, then back in again (or run C<". .bashrc"> if you |
186 | prefer). Finally, edit C<.cpan/CPAN/MyConfig.pm> and add |
187 | |
188 | 'make_install_arg' => qq[SITEPREFIX=$ENV{HOME}/local], |
189 | 'makepl_arg' => qq[INSTALLDIRS=site install_base=$ENV{HOME}/local], |
190 | |
191 | Now you can install the modules you need using CPAN as normal; they |
192 | will be installed into your local directory, and perl will pick them |
193 | up. Finally, change directory into the root of your virtual host and |
194 | symlink your application's script directory in: |
195 | |
196 | cd path/to/mydomain.com |
197 | ln -s ~/lib/MyApp/script script |
198 | |
199 | And add the following lines to your .htaccess file (assuming the server |
200 | is setup to handle .pl as fcgi - you may need to rename the script to |
201 | myapp_fastcgi.fcgi and/or use a SetHandler directive): |
202 | |
203 | RewriteEngine On |
204 | RewriteCond %{REQUEST_URI} !^/?script/myapp_fastcgi.pl |
205 | RewriteRule ^(.*)$ script/myapp_fastcgi.pl/$1 [PT,L] |
206 | |
207 | Now C<http://mydomain.com/> should now Just Work. Congratulations, now |
208 | you can tell your friends about your new website (or in our case, tell |
209 | the client it's time to pay the invoice :) ) |
210 | |
211 | =head2 FastCGI Deployment |
212 | |
213 | FastCGI is a high-performance extension to CGI. It is suitable |
214 | for production environments. |
215 | |
216 | =head3 Pros |
217 | |
218 | =head4 Speed |
219 | |
220 | FastCGI performs equally as well as mod_perl. Don't let the 'CGI' fool you; |
221 | your app runs as multiple persistent processes ready to receive connections |
222 | from the web server. |
223 | |
224 | =head4 App Server |
225 | |
226 | When using external FastCGI servers, your application runs as a standalone |
227 | application server. It may be restarted independently from the web server. |
228 | This allows for a more robust environment and faster reload times when |
229 | pushing new app changes. The frontend server can even be configured to |
230 | display a friendly "down for maintenance" page while the application is |
231 | restarting. |
232 | |
233 | =head4 Load-balancing |
234 | |
235 | You can launch your application on multiple backend servers and allow the |
236 | frontend web server to load-balance between all of them. And of course, if |
237 | one goes down, your app continues to run fine. |
238 | |
239 | =head4 Multiple versions of the same app |
240 | |
241 | Each FastCGI application is a separate process, so you can run different |
242 | versions of the same app on a single server. |
243 | |
244 | =head4 Can run with threaded Apache |
245 | |
246 | Since your app is not running inside of Apache, the faster mpm_worker module |
247 | can be used without worrying about the thread safety of your application. |
248 | |
249 | =head3 Cons |
250 | |
251 | You may have to disable mod_deflate. If you experience page hangs with |
252 | mod_fastcgi then remove deflate.load and deflate.conf from mods-enabled/ |
253 | |
254 | =head4 More complex environment |
255 | |
256 | With FastCGI, there are more things to monitor and more processes running |
257 | than when using mod_perl. |
258 | |
259 | =head3 Setup |
260 | |
261 | =head4 1. Install Apache with mod_fastcgi |
262 | |
263 | mod_fastcgi for Apache is a third party module, and can be found at |
264 | L<http://www.fastcgi.com/>. It is also packaged in many distributions, |
265 | for example, libapache2-mod-fastcgi in Debian. You will also need to install |
266 | the L<FCGI> module from cpan. |
267 | |
268 | Important Note! If you experience difficulty properly rendering pages, |
269 | try disabling Apache's mod_deflate (Deflate Module), e.g. 'a2dismod deflate'. |
270 | |
271 | =head4 2. Configure your application |
272 | |
273 | # Serve static content directly |
274 | DocumentRoot /var/www/MyApp/root |
275 | Alias /static /var/www/MyApp/root/static |
276 | |
277 | FastCgiServer /var/www/MyApp/script/myapp_fastcgi.pl -processes 3 |
278 | Alias /myapp/ /var/www/MyApp/script/myapp_fastcgi.pl/ |
279 | |
280 | # Or, run at the root |
281 | Alias / /var/www/MyApp/script/myapp_fastcgi.pl/ |
282 | |
283 | The above commands will launch 3 app processes and make the app available at |
284 | /myapp/ |
285 | |
286 | =head3 Standalone server mode |
287 | |
288 | While not as easy as the previous method, running your app as an external |
289 | server gives you much more flexibility. |
290 | |
291 | First, launch your app as a standalone server listening on a socket. |
292 | |
293 | script/myapp_fastcgi.pl -l /tmp/myapp.socket -n 5 -p /tmp/myapp.pid -d |
294 | |
295 | You can also listen on a TCP port if your web server is not on the same |
296 | machine. |
297 | |
298 | script/myapp_fastcgi.pl -l :8080 -n 5 -p /tmp/myapp.pid -d |
299 | |
300 | You will probably want to write an init script to handle starting/stopping |
301 | of the app using the pid file. |
302 | |
303 | Now, we simply configure Apache to connect to the running server. |
304 | |
305 | # 502 is a Bad Gateway error, and will occur if the backend server is down |
306 | # This allows us to display a friendly static page that says "down for |
307 | # maintenance" |
308 | Alias /_errors /var/www/MyApp/root/error-pages |
309 | ErrorDocument 502 /_errors/502.html |
310 | |
311 | FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/myapp.socket |
312 | Alias /myapp/ /tmp/myapp.fcgi/ |
313 | |
314 | # Or, run at the root |
315 | Alias / /tmp/myapp.fcgi/ |
316 | |
317 | =head3 More Info |
318 | |
319 | L<Catalyst::Engine::FastCGI>. |
320 | |
321 | =head2 Development server deployment |
322 | |
323 | The development server is a mini web server written in perl. If you |
324 | expect a low number of hits or you don't need mod_perl/FastCGI speed, |
325 | you could use the development server as the application server with a |
326 | lightweight proxy web server at the front. However, consider using |
327 | L<Catalyst::Engine::HTTP::Prefork> for this kind of deployment instead, since |
328 | it can better handle multiple concurrent requests without forking, or can |
329 | prefork a set number of servers for improved performance. |
330 | |
331 | =head3 Pros |
332 | |
333 | As this is an application server setup, the pros are the same as |
334 | FastCGI (with the exception of speed). |
335 | It is also: |
336 | |
337 | =head4 Simple |
338 | |
339 | The development server is what you create your code on, so if it works |
340 | here, it should work in production! |
341 | |
342 | =head3 Cons |
343 | |
344 | =head4 Speed |
345 | |
346 | Not as fast as mod_perl or FastCGI. Needs to fork for each request |
347 | that comes in - make sure static files are served by the web server to |
348 | save forking. |
349 | |
350 | =head3 Setup |
351 | |
352 | =head4 Start up the development server |
353 | |
354 | script/myapp_server.pl -p 8080 -k -f -pidfile=/tmp/myapp.pid |
355 | |
356 | You will probably want to write an init script to handle stop/starting |
357 | the app using the pid file. |
358 | |
359 | =head4 Configuring Apache |
360 | |
361 | Make sure mod_proxy is enabled and add: |
362 | |
363 | # Serve static content directly |
364 | DocumentRoot /var/www/MyApp/root |
365 | Alias /static /var/www/MyApp/root/static |
366 | |
367 | ProxyRequests Off |
368 | <Proxy *> |
369 | Order deny,allow |
370 | Allow from all |
371 | </Proxy> |
372 | |
373 | # Need to specifically stop these paths from being passed to proxy |
374 | ProxyPass /static ! |
375 | ProxyPass /favicon.ico ! |
376 | |
377 | ProxyPass / http://localhost:8080/ |
378 | ProxyPassReverse / http://localhost:8080/ |
379 | |
380 | # This is optional if you'd like to show a custom error page |
381 | # if the proxy is not available |
382 | ErrorDocument 502 /static/error_pages/http502.html |
383 | |
384 | You can wrap the above within a VirtualHost container if you want |
385 | different apps served on the same host. |
386 | |
01b62b15 |
387 | =head1 AUTHORS |
388 | |
389 | Catalyst Contributors, see Catalyst.pm |
390 | |
391 | =head1 COPYRIGHT |
392 | |
393 | This library is free software. You can redistribute it and/or modify it under |
394 | the same terms as Perl itself. |
395 | |
396 | =cut |
19a5b486 |
397 | |