rt 4.0.23
[freeside.git] / rt / devel / tools / rt-apache
1 #!/usr/bin/env perl
2
3 # BEGIN BPS TAGGED BLOCK {{{
4 #
5 # COPYRIGHT:
6 #
7 # This software is Copyright (c) 1996-2015 Best Practical Solutions, LLC
8 #                                          <sales@bestpractical.com>
9 #
10 # (Except where explicitly superseded by other copyright notices)
11 #
12 #
13 # LICENSE:
14 #
15 # This work is made available to you under the terms of Version 2 of
16 # the GNU General Public License. A copy of that license should have
17 # been provided with this software, but in any event can be snarfed
18 # from www.gnu.org.
19 #
20 # This work is distributed in the hope that it will be useful, but
21 # WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23 # General Public License for more details.
24 #
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 # 02110-1301 or visit their web page on the internet at
29 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
30 #
31 #
32 # CONTRIBUTION SUBMISSION POLICY:
33 #
34 # (The following paragraph is not intended to limit the rights granted
35 # to you to modify and distribute this software under the terms of
36 # the GNU General Public License and is only of importance to you if
37 # you choose to contribute your changes and enhancements to the
38 # community by submitting them to Best Practical Solutions, LLC.)
39 #
40 # By intentionally submitting any modifications, corrections or
41 # derivatives to this work, or any other work intended for use with
42 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
43 # you are the copyright holder for those contributions and you grant
44 # Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
45 # royalty-free, perpetual, license to use, copy, create derivative
46 # works based on those contributions, and sublicense and distribute
47 # those contributions and any derivatives thereof.
48 #
49 # END BPS TAGGED BLOCK }}}
50 use strict;
51 use warnings;
52
53 use Getopt::Long;
54 use FindBin;
55 use Pod::Usage;
56 use File::Spec::Functions qw(rel2abs);
57
58 my %opt = (
59     root => ($ENV{RTHOME} || "/opt/rt4"),
60
61     fcgid   => 0,
62     fastcgi => 0,
63     perl    => 0,
64
65     modules => "/usr/lib/apache2/modules",
66 );
67
68 GetOptions(  \%opt,
69     "root=s",
70
71     "rt3|3!",
72
73     "fcgid!",
74     "fastcgi!",
75     "perl!",
76
77     "port|p=i",
78     "ssl:i",
79     "single|X",
80
81     "modules=s",
82
83     "help|h|?",
84 ) or pod2usage( 1 );
85 pod2usage( {verbose => 2} ) if $opt{help};
86
87 # All paths must be absolute
88 $opt{$_} = rel2abs($opt{$_})
89     for qw(root modules);
90
91 # Determine what module to use
92 my $mod;
93 if ($opt{fcgid} + $opt{fastcgi} + $opt{perl} > 1) {
94     die "Can only supply one of fcgid, fastcgi, or perl\n";
95 } elsif ($opt{fcgid} + $opt{fastcgi} + $opt{perl} == 0) {
96     my @guess = qw(fastcgi fcgid perl);
97     @guess = grep {-f "$opt{modules}/mod_$_.so"} @guess;
98     die "Neither mod_fcgid, mod_fastcgi, nor mod_perl are installed; aborting\n"
99         unless @guess;
100     warn "No deployment given -- assuming mod_$guess[0] deployment\n";
101     $mod = $guess[0];
102 } else {
103     $mod = (grep {$opt{$_}} qw(fastcgi fcgid perl))[0];
104 }
105
106 # Sanity check that the root contains an RT install
107 die "$opt{root} doesn't look like an RT install\n"
108     unless -e "$opt{root}/lib/RT.pm";
109
110 # Detect if we are actually rt3
111 if (not -e "$opt{root}/sbin/rt-server.fcgi"
112         and -e "$opt{root}/bin/mason_handler.fcgi") {
113     $opt{rt3}++;
114     warn "RT3 install detected!\n";
115 }
116
117 # Parse etc/RT_SiteConfig.pm for the default port
118 my $RTCONF;
119 $opt{port} ||= parseconf( "WebPort" );
120 unless ($opt{port}) {
121     warn "Defaulting to port 8888\n";
122     $opt{port} = 8888;
123 }
124
125 # Set ssl port if they want it but didn't provide a number
126 $opt{ssl} = 4430 if defined $opt{ssl} and not $opt{ssl};
127
128 # Parse out the WebPath
129 my $path = parseconf( "WebPath" ) || "";
130
131 my $template = join("", <DATA>);
132 $template =~ s/\$PORT/$opt{port}/g;
133 $template =~ s!\$PATH/!$path/!g;
134 $template =~ s!\$PATH!$path || "/"!ge;
135 $template =~ s/\$SSL/$opt{ssl} || 0/ge;
136 $template =~ s/\$RTHOME/$opt{root}/g;
137 $template =~ s/\$MODULES/$opt{modules}/g;
138 $template =~ s/\$TOOLS/$FindBin::Bin/g;
139 $template =~ s/\$PROCESSES/$opt{single} ? 1 : 3/ge;
140
141 my $conf = "$opt{root}/var/apache.conf";
142 open(CONF, ">", $conf)
143     or die "Can't write $conf: $!";
144 print CONF $template;
145 close CONF;
146
147 my @opts = ("-f", $conf, "-D" . uc($mod) );
148 push @opts, "-DSSL" if $opt{ssl};
149 push @opts, "-DRT3" if $opt{rt3};
150 push @opts, "-DSINGLE" if $opt{single};
151
152 # Wait for a previous run to terminate
153 if ( open( PIDFILE, "<", "$opt{root}/var/apache2.pid") ) {
154     my $pid = <PIDFILE>;
155     chomp $pid;
156     close PIDFILE;
157     if ($pid and kill 0, $pid) {
158         warn "Waiting for previous run (pid $pid) to finish...\n";
159         sleep 1 while kill 0, $pid;
160     }
161 }
162
163 # Clean out the log in preparation
164 my $log = "$opt{root}/var/log/apache-error.log";
165 unlink($log);
166
167 # Start 'er up
168 warn "Starting apache server on http://localhost:$opt{port}$path/"
169     . ($opt{ssl} ? " and https://localhost:$opt{ssl}$path/" : "") . "\n";
170 !system("apache2", @opts, "-k", "start")
171     or die "Can't exec apache2: $@";
172 # Ignore the return value, as we expect it to be ^C'd
173 system("tail", "-f", $log);
174 warn "Shutting down apache...\n";
175 !system("apache2", @opts, "-k", "stop")
176     or die "Can't exec apache2: $@";
177
178
179 sub parseconf {
180     my ($optname) = @_;
181     # We're going to be evil, and try to parse the config
182     unless (defined $RTCONF) {
183         unless ( open(CONF, "<", "$opt{root}/etc/RT_SiteConfig.pm") ) {
184             warn "Can't open $opt{root}/etc/RT_SiteConfig.pm: $!\n";
185             $RTCONF = "";
186             return;
187         }
188         $RTCONF = join("", <CONF>);
189         close CONF;
190     }
191
192     return unless $RTCONF =~ /^\s*Set\(\s*\$$optname\s*(?:,|=>)\s*['"]?(.*?)['"]?\s*\)/m;
193     return $1;
194 }
195
196 =head1 NAME
197
198 rt-apache - Wrapper to start Apache running RT
199
200 =head1 DESCRIPTION
201
202 This script exists to make it easier to run RT under Apache for testing.
203 It is not intended as a way to deploy RT, or to provide example Apache
204 configuration for RT.  For instructions on how to deploy RT with Apache,
205 please read the provided F<docs/web_deployment.pod> file.
206
207 Running this script will start F<apache2> with a custom-built
208 configuration file, built based on command-line options and the contents
209 of your F<RT_SiteConfig.pm>.  It will work with either RT 3.8.x or RT
210 4.0.x.  As it is primarily for simple testing, it runs Apache as the
211 current user.
212
213 =head1 OPTIONS
214
215 C<rt-apache> will parse your F<RT_SiteConfig.pm> for its C<WebPath> and
216 C<WebPort> configuration, and adjust its defaults accordingly.
217
218 =over
219
220 =item --root B<path>
221
222 The path to the RT install to serve.  This defaults to the C<RTHOME>
223 environment variable, or C</opt/rt4>.
224
225 =item --fastcgi, --fcgid, --perl
226
227 Determines the Apache module which is used.  By default, the first one
228 of that list which exists will be used.  See also L</--modules>.
229
230 =item --port B<number>
231
232 Choses the port to listen on.  By default, this is parsed from the
233 F<RT_SiteConfig.pm>, and falling back to 8888.
234
235 =item --ssl [B<number>]
236
237 Also listens on the provided port with HTTPS, using a self-signed
238 certificate for C<localhost>.  If the port number is not specified,
239 defaults to port 4430.
240
241 =item --single, -X
242
243 Run only one process or thread, for ease of debugging.
244
245 =item --rt3, -3
246
247 Declares that the RT install in question is RT 3.8.x.  C<rt-apache> can
248 usually detect this for you, however.
249
250 =item --modules B<path>
251
252 The path to the Apache2 modules directory, which is expected to contain
253 at least one of F<mod_fcgid.so>, F<mod_fastcgi.so>, or F<mod_perl.so>.
254 Defaults to F</usr/lib/apache2/modules>.
255
256 =back
257
258 =cut
259
260 __DATA__
261 <IfDefine SINGLE>
262     <IfModule mpm_prefork_module>
263         StartServers          1
264         MinSpareServers       1
265         MaxSpareServers       1
266         MaxClients            1
267         MaxRequestsPerChild   0
268     </IfModule>
269
270     <IfModule mpm_worker_module>
271         StartServers          1
272         MinSpareThreads       1
273         MaxSpareThreads       1
274         ThreadLimit           1
275         ThreadsPerChild       1
276         MaxClients            1
277         MaxRequestsPerChild   0
278     </IfModule>
279 </IfDefine>
280
281 Listen $PORT
282 <IfDefine SSL>
283    Listen $SSL
284 </IfDefine>
285
286 ServerName localhost
287 ServerRoot $RTHOME/var
288 PidFile    $RTHOME/var/apache2.pid
289 LockFile   $RTHOME/var/apache2.lock
290 ServerAdmin root@localhost
291
292 LoadModule authz_host_module  $MODULES/mod_authz_host.so
293 LoadModule env_module         $MODULES/mod_env.so
294 LoadModule alias_module       $MODULES/mod_alias.so
295 LoadModule mime_module        $MODULES/mod_mime.so
296 TypesConfig $TOOLS/mime.types
297
298 <IfDefine PERL>
299     LoadModule perl_module    $MODULES/mod_perl.so
300 </IfDefine>
301 <IfDefine FASTCGI>
302     LoadModule fastcgi_module $MODULES/mod_fastcgi.so
303 </IfDefine>
304 <IfDefine FCGID>
305     LoadModule fcgid_module   $MODULES/mod_fcgid.so
306 </IfDefine>
307 <IfDefine SSL>
308     LoadModule ssl_module     $MODULES/mod_ssl.so
309 </IfDefine>
310
311 <IfModule !log_config_module>
312     LoadModule log_config_module $MODULES/mod_log_config.so
313 </IfModule>
314 ErrorLog    "$RTHOME/var/log/apache-error.log"
315 TransferLog "$RTHOME/var/log/apache-access.log"
316 LogLevel notice
317
318 <Directory />
319     Options FollowSymLinks
320     AllowOverride None
321     Order deny,allow
322     Deny from all
323 </Directory>
324
325 AddDefaultCharset UTF-8
326
327 DocumentRoot $RTHOME/share/html
328 <Directory $RTHOME/share/html>
329     Order allow,deny
330     Allow from all
331 </Directory>
332
333 Alias $PATH/NoAuth/images/ $RTHOME/share/html/NoAuth/images/
334 <Directory $RTHOME/share/html/NoAuth/images>
335     Order allow,deny
336     Allow from all
337 </Directory>
338
339 <IfDefine !RT3>
340 ########## 4.0 mod_perl
341 <IfDefine PERL>
342     PerlSetEnv RT_SITE_CONFIG $RTHOME/etc/RT_SiteConfig.pm
343     <Location $PATH>
344         Order allow,deny
345         Allow from all
346         SetHandler modperl
347         PerlResponseHandler Plack::Handler::Apache2
348         PerlSetVar psgi_app $RTHOME/sbin/rt-server
349     </Location>
350     <Perl>
351         use Plack::Handler::Apache2;
352         Plack::Handler::Apache2->preload("$RTHOME/sbin/rt-server");
353     </Perl>
354 </IfDefine>
355
356 ########## 4.0 mod_fastcgi
357 <IfDefine FASTCGI>
358     FastCgiIpcDir $RTHOME/var
359     FastCgiServer $RTHOME/sbin/rt-server.fcgi -processes $PROCESSES -idle-timeout 300
360     ScriptAlias $PATH $RTHOME/sbin/rt-server.fcgi/
361     <Location $PATH>
362         Order allow,deny
363         Allow from all
364         Options +ExecCGI
365         AddHandler fastcgi-script fcgi
366     </Location>
367 </IfDefine>
368
369 ########## 4.0 mod_fcgid
370 <IfDefine FCGID>
371     FcgidProcessTableFile $RTHOME/var/fcgid_shm
372     FcgidIPCDir $RTHOME/var
373     FcgidMaxRequestLen 1073741824
374     ScriptAlias $PATH $RTHOME/sbin/rt-server.fcgi/
375     <Location $PATH>
376         Order allow,deny
377         Allow from all
378         Options +ExecCGI
379         AddHandler fcgid-script fcgi
380     </Location>
381 </IfDefine>
382 </IfDefine>
383
384
385 <IfDefine RT3>
386 ########## 3.8 mod_perl
387 <IfDefine PERL>
388     PerlSetEnv RT_SITE_CONFIG $RTHOME/etc/RT_SiteConfig.pm
389     PerlRequire "$RTHOME/bin/webmux.pl"
390     <Location $PATH/NoAuth/images>
391         SetHandler default
392     </Location>
393     <Location $PATH>
394         SetHandler perl-script
395         PerlResponseHandler RT::Mason
396     </Location>
397 </IfDefine>
398
399 ########## 3.8 mod_fastcgi
400 <IfDefine FASTCGI>
401     FastCgiIpcDir $RTHOME/var
402     FastCgiServer $RTHOME/bin/mason_handler.fcgi -processes $PROCESSES -idle-timeout 300
403     ScriptAlias $PATH $RTHOME/bin/mason_handler.fcgi/
404     <Location $PATH>
405         Order allow,deny
406         Allow from all
407         Options +ExecCGI
408         AddHandler fastcgi-script fcgi
409     </Location>
410 </IfDefine>
411
412 ########## 3.8 mod_fcgid
413 <IfDefine FCGID>
414     FcgidProcessTableFile $RTHOME/var/fcgid_shm
415     FcgidIPCDir $RTHOME/var
416     FcgidMaxRequestLen 1073741824
417     ScriptAlias $PATH $RTHOME/bin/mason_handler.fcgi/
418     <Location $PATH>
419         Order allow,deny
420         Allow from all
421         Options +ExecCGI
422         AddHandler fcgid-script fcgi
423     </Location>
424 </IfDefine>
425 </IfDefine>
426
427 <IfDefine SSL>
428     SSLRandomSeed startup builtin
429     SSLRandomSeed startup file:/dev/urandom 512
430     SSLRandomSeed connect builtin
431     SSLRandomSeed connect file:/dev/urandom 512
432     SSLSessionCache shmcb:$RTHOME/var/ssl_scache(512000)
433     SSLMutex file:$RTHOME/var/ssl_mutex
434     <VirtualHost *:$SSL>
435         SSLEngine on
436         SSLCertificateFile    $TOOLS/localhost.crt
437         SSLCertificateKeyFile $TOOLS/localhost.key
438     </VirtualHost>
439 </IfDefine>