rt 4.2.16
[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-2019 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     "auth|A:s",
81
82     "modules=s",
83
84     "help|h|?",
85 ) or pod2usage( 1 );
86 pod2usage( {verbose => 2} ) if $opt{help};
87
88 # All paths must be absolute
89 $opt{$_} = rel2abs($opt{$_})
90     for qw(root modules);
91
92 # Determine what module to use
93 my $mod;
94 if ($opt{fcgid} + $opt{fastcgi} + $opt{perl} > 1) {
95     die "Can only supply one of fcgid, fastcgi, or perl\n";
96 } elsif ($opt{fcgid} + $opt{fastcgi} + $opt{perl} == 0) {
97     my @guess = qw(fastcgi fcgid perl);
98     @guess = grep {-f "$opt{modules}/mod_$_.so"} @guess;
99     die "Neither mod_fcgid, mod_fastcgi, nor mod_perl are installed; aborting\n"
100         unless @guess;
101     warn "No deployment given -- assuming mod_$guess[0] deployment\n";
102     $mod = $guess[0];
103 } else {
104     $mod = (grep {$opt{$_}} qw(fastcgi fcgid perl))[0];
105 }
106
107 # Sanity check that the root contains an RT install
108 die "$opt{root} doesn't look like an RT install\n"
109     unless -e "$opt{root}/lib/RT.pm";
110
111 # Detect if we are actually rt3
112 if (not -e "$opt{root}/sbin/rt-server.fcgi"
113         and -e "$opt{root}/bin/mason_handler.fcgi") {
114     $opt{rt3}++;
115     warn "RT3 install detected!\n";
116 }
117
118 # Parse etc/RT_SiteConfig.pm for the default port
119 my $RTCONF;
120 $opt{port} ||= parseconf( "WebPort" );
121 unless ($opt{port}) {
122     warn "Defaulting to port 8888\n";
123     $opt{port} = 8888;
124 }
125
126 # Set ssl port if they want it but didn't provide a number
127 $opt{ssl} = 4430 if defined $opt{ssl} and not $opt{ssl};
128
129 # Default auth to on if they set $WebRemoteUserAuth
130 $opt{auth} = '' if not exists $opt{auth} and parseconf( "WebRemoteUserAuth" );
131
132 # Set an auth path if they want it but didn't pass a path
133 if (defined $opt{auth} and not $opt{auth}) {
134     $opt{auth} = "$opt{root}/var/htpasswd";
135     unless (-f $opt{auth}) {
136         open(my $fh, ">", $opt{auth}) or die "Can't create default htpasswd: $!";
137         print $fh 'root:$apr1$TZA4Y0DL$DS5ZhDH8QrhB.uAtvNJmh.' . "\n";
138         close $fh or die "Can't create default htpasswd: $!";
139     }
140 } elsif ($opt{auth} and not -f $opt{auth}) {
141     die "Can't read htpasswd file $opt{auth}!";
142 }
143
144 # Parse out the WebPath
145 my $path = parseconf( "WebPath" ) || "";
146
147 my $template = join("", <DATA>);
148 $template =~ s/\$PORT/$opt{port}/g;
149 $template =~ s!\$PATH/!$path/!g;
150 $template =~ s!\$PATH!$path || "/"!ge;
151 $template =~ s/\$SSL/$opt{ssl} || 0/ge;
152 $template =~ s/\$AUTH/$opt{auth}/ge;
153 $template =~ s/\$RTHOME/$opt{root}/g;
154 $template =~ s/\$MODULES/$opt{modules}/g;
155 $template =~ s/\$TOOLS/$FindBin::Bin/g;
156 $template =~ s/\$PROCESSES/$opt{single} ? 1 : 3/ge;
157
158 my $conf = "$opt{root}/var/apache.conf";
159 open(CONF, ">", $conf)
160     or die "Can't write $conf: $!";
161 print CONF $template;
162 close CONF;
163
164 my @opts = ("-f", $conf, "-D" . uc($mod) );
165 push @opts, "-DSSL" if $opt{ssl};
166 push @opts, "-DRT3" if $opt{rt3};
167 push @opts, "-DSINGLE" if $opt{single};
168
169 # Wait for a previous run to terminate
170 if ( open( PIDFILE, "<", "$opt{root}/var/apache2.pid") ) {
171     my $pid = <PIDFILE>;
172     chomp $pid;
173     close PIDFILE;
174     if ($pid and kill 0, $pid) {
175         warn "Waiting for previous run (pid $pid) to finish...\n";
176         sleep 1 while kill 0, $pid;
177     }
178 }
179
180 # Clean out the log in preparation
181 my $log = "$opt{root}/var/log/apache-error.log";
182 unlink($log);
183
184 # Start 'er up
185 warn "Starting apache server on http://localhost:$opt{port}$path/"
186     . ($opt{ssl} ? " and https://localhost:$opt{ssl}$path/" : "") . "\n";
187 !system("apache2", @opts, "-k", "start")
188     or die "Can't exec apache2: $@";
189 # Ignore the return value, as we expect it to be ^C'd
190 system("tail", "-f", $log);
191 warn "Shutting down apache...\n";
192 !system("apache2", @opts, "-k", "stop")
193     or die "Can't exec apache2: $@";
194
195
196 sub parseconf {
197     my ($optname) = @_;
198     # We're going to be evil, and try to parse the config
199     unless (defined $RTCONF) {
200         unless ( open(CONF, "<", "$opt{root}/etc/RT_SiteConfig.pm") ) {
201             warn "Can't open $opt{root}/etc/RT_SiteConfig.pm: $!\n";
202             $RTCONF = "";
203             return;
204         }
205         $RTCONF = join("", <CONF>);
206         close CONF;
207     }
208
209     return unless $RTCONF =~ /^\s*Set\(\s*\$$optname\s*(?:,|=>)\s*['"]?(.*?)['"]?\s*\)/m;
210     return $1;
211 }
212
213 =head1 NAME
214
215 rt-apache - Wrapper to start Apache running RT
216
217 =head1 DESCRIPTION
218
219 This script exists to make it easier to run RT under Apache for testing.
220 It is not intended as a way to deploy RT, or to provide example Apache
221 configuration for RT.  For instructions on how to deploy RT with Apache,
222 please read the provided F<docs/web_deployment.pod> file.
223
224 Running this script will start F<apache2> with a custom-built
225 configuration file, built based on command-line options and the contents
226 of your F<RT_SiteConfig.pm>.  It will work with either RT 3.8.x or RT
227 4.0.x.  As it is primarily for simple testing, it runs Apache as the
228 current user.
229
230 =head1 OPTIONS
231
232 C<rt-apache> will parse your F<RT_SiteConfig.pm> for its C<WebPath> and
233 C<WebPort> configuration, and adjust its defaults accordingly.
234
235 =over
236
237 =item --root B<path>
238
239 The path to the RT install to serve.  This defaults to the C<RTHOME>
240 environment variable, or C</opt/rt4>.
241
242 =item --fastcgi, --fcgid, --perl
243
244 Determines the Apache module which is used.  By default, the first one
245 of that list which exists will be used.  See also L</--modules>.
246
247 =item --port B<number>, -p
248
249 Choses the port to listen on.  By default, this is parsed from the
250 F<RT_SiteConfig.pm>, and falling back to 8888.
251
252 =item --ssl [B<number>]
253
254 Also listens on the provided port with HTTPS, using a self-signed
255 certificate for C<localhost>.  If the port number is not specified,
256 defaults to port 4430.
257
258 =item --auth [F</path/to/htpasswd>], -A
259
260 Turns on HTTP Basic Authentication; this is done automatically if
261 C<$WebRemoteUserAuth> is set in the F<RT_SiteConfig.pm>.  The provided
262 path should be to a F<htpasswd> file; if not given, defaults to a file
263 containing only user C<root> with password C<password>.
264
265 =item --single, -X
266
267 Run only one process or thread, for ease of debugging.
268
269 =item --rt3, -3
270
271 Declares that the RT install in question is RT 3.8.x.  C<rt-apache> can
272 usually detect this for you, however.
273
274 =item --modules B<path>
275
276 The path to the Apache2 modules directory, which is expected to contain
277 at least one of F<mod_fcgid.so>, F<mod_fastcgi.so>, or F<mod_perl.so>.
278 Defaults to F</usr/lib/apache2/modules>.
279
280 =back
281
282 =cut
283
284 __DATA__
285 Listen $PORT
286 <IfDefine SSL>
287    Listen $SSL
288 </IfDefine>
289
290 ServerName localhost
291 ServerRoot $RTHOME/var
292 PidFile    $RTHOME/var/apache2.pid
293 <IfVersion < 2.4>
294     LockFile   $RTHOME/var/apache2.lock
295 </IfVersion>
296 ServerAdmin root@localhost
297
298 <IfVersion >= 2.4>
299     LoadModule mpm_prefork_module $MODULES/mod_mpm_prefork.so
300     LoadModule authz_core_module $MODULES/mod_authz_core.so
301 </IfVersion>
302 LoadModule authz_host_module  $MODULES/mod_authz_host.so
303 LoadModule env_module         $MODULES/mod_env.so
304 LoadModule alias_module       $MODULES/mod_alias.so
305 LoadModule mime_module        $MODULES/mod_mime.so
306 TypesConfig $TOOLS/mime.types
307
308 <IfDefine SINGLE>
309     <IfModule mpm_prefork_module>
310         StartServers          1
311         MinSpareServers       1
312         MaxSpareServers       1
313         MaxClients            1
314         MaxRequestsPerChild   0
315     </IfModule>
316
317     <IfModule mpm_worker_module>
318         StartServers          1
319         MinSpareThreads       1
320         MaxSpareThreads       1
321         ThreadLimit           1
322         ThreadsPerChild       1
323         MaxClients            1
324         MaxRequestsPerChild   0
325     </IfModule>
326 </IfDefine>
327
328 <IfDefine PERL>
329     LoadModule perl_module    $MODULES/mod_perl.so
330 </IfDefine>
331 <IfDefine FASTCGI>
332     LoadModule fastcgi_module $MODULES/mod_fastcgi.so
333 </IfDefine>
334 <IfDefine FCGID>
335     LoadModule fcgid_module   $MODULES/mod_fcgid.so
336 </IfDefine>
337 <IfDefine SSL>
338     LoadModule ssl_module     $MODULES/mod_ssl.so
339     <IfVersion >= 2.4>
340         LoadModule socache_shmcb_module $MODULES/mod_socache_shmcb.so
341     </IfVersion>
342 </IfDefine>
343
344 <IfModule !log_config_module>
345     LoadModule log_config_module $MODULES/mod_log_config.so
346 </IfModule>
347 ErrorLog    "$RTHOME/var/log/apache-error.log"
348 TransferLog "$RTHOME/var/log/apache-access.log"
349 LogLevel notice
350
351 <Directory />
352     Options FollowSymLinks
353     AllowOverride None
354     Order deny,allow
355     Deny from all
356 </Directory>
357
358 AddDefaultCharset UTF-8
359
360 DocumentRoot $RTHOME/share/html
361 <Directory $RTHOME/share/html>
362     Order allow,deny
363     Allow from all
364 </Directory>
365
366 Alias $PATH/NoAuth/images/ $RTHOME/share/html/NoAuth/images/
367 <Directory $RTHOME/share/html/NoAuth/images>
368     Order allow,deny
369     Allow from all
370 </Directory>
371
372 <IfDefine !RT3>
373 ########## 4.0 mod_perl
374 <IfDefine PERL>
375     PerlSetEnv RT_SITE_CONFIG $RTHOME/etc/RT_SiteConfig.pm
376     <Location $PATH>
377         SetHandler modperl
378         PerlResponseHandler Plack::Handler::Apache2
379         PerlSetVar psgi_app $RTHOME/sbin/rt-server
380     </Location>
381     <Perl>
382         use Plack::Handler::Apache2;
383         Plack::Handler::Apache2->preload("$RTHOME/sbin/rt-server");
384     </Perl>
385 </IfDefine>
386
387 ########## 4.0 mod_fastcgi
388 <IfDefine FASTCGI>
389     FastCgiIpcDir $RTHOME/var
390     FastCgiServer $RTHOME/sbin/rt-server.fcgi -processes $PROCESSES -idle-timeout 300
391     ScriptAlias $PATH $RTHOME/sbin/rt-server.fcgi/
392     <Location $PATH>
393         Options +ExecCGI
394         AddHandler fastcgi-script fcgi
395     </Location>
396 </IfDefine>
397
398 ########## 4.0 mod_fcgid
399 <IfDefine FCGID>
400     FcgidProcessTableFile $RTHOME/var/fcgid_shm
401     FcgidIPCDir $RTHOME/var
402     FcgidMaxRequestLen 1073741824
403     ScriptAlias $PATH $RTHOME/sbin/rt-server.fcgi/
404     <Location $PATH>
405         Options +ExecCGI
406         AddHandler fcgid-script fcgi
407     </Location>
408 </IfDefine>
409 </IfDefine>
410
411
412 <IfDefine RT3>
413 ########## 3.8 mod_perl
414 <IfDefine PERL>
415     PerlSetEnv RT_SITE_CONFIG $RTHOME/etc/RT_SiteConfig.pm
416     PerlRequire "$RTHOME/bin/webmux.pl"
417     <Location $PATH/NoAuth/images>
418         SetHandler default
419     </Location>
420     <Location $PATH>
421         SetHandler perl-script
422         PerlResponseHandler RT::Mason
423     </Location>
424 </IfDefine>
425
426 ########## 3.8 mod_fastcgi
427 <IfDefine FASTCGI>
428     FastCgiIpcDir $RTHOME/var
429     FastCgiServer $RTHOME/bin/mason_handler.fcgi -processes $PROCESSES -idle-timeout 300
430     ScriptAlias $PATH $RTHOME/bin/mason_handler.fcgi/
431     <Location $PATH>
432         Options +ExecCGI
433         AddHandler fastcgi-script fcgi
434     </Location>
435 </IfDefine>
436
437 ########## 3.8 mod_fcgid
438 <IfDefine FCGID>
439     FcgidProcessTableFile $RTHOME/var/fcgid_shm
440     FcgidIPCDir $RTHOME/var
441     FcgidMaxRequestLen 1073741824
442     ScriptAlias $PATH $RTHOME/bin/mason_handler.fcgi/
443     <Location $PATH>
444         Options +ExecCGI
445         AddHandler fcgid-script fcgi
446     </Location>
447 </IfDefine>
448 </IfDefine>
449
450 <IfDefine SSL>
451     SSLRandomSeed startup builtin
452     SSLRandomSeed startup file:/dev/urandom 512
453     SSLRandomSeed connect builtin
454     SSLRandomSeed connect file:/dev/urandom 512
455     SSLSessionCache shmcb:$RTHOME/var/ssl_scache(512000)
456     <IfVersion < 2.4>
457         SSLMutex file:$RTHOME/var/ssl_mutex
458     </IfVersion>
459     <VirtualHost *:$SSL>
460         SSLEngine on
461         SSLCertificateFile    $TOOLS/localhost.crt
462         SSLCertificateKeyFile $TOOLS/localhost.key
463     </VirtualHost>
464 </IfDefine>