Apache deployment

Aaron W. Swenson edited this page Jan 27, 2018 · 5 revisions

Apache deployment

Apache/mod_proxy Preamble

It is important for you to note that the Apache2 modules mod_proxy and mod_proxy_http must be enabled.

 LoadModule proxy_module lib/httpd/mod_proxy.so
 LoadModule proxy_http_module lib/httpd/mod_proxy_http.so

It is also important to set permissions for proxying for security purposes, below is an example.

 <Proxy *>
   Order allow,deny
   Allow from all
 </Proxy>

Apache/mod_proxy (Host name)

If you want to deploy multiple applications, it is easy to use virtual-host and mod_proxy in Apache.

 <VirtualHost *:80>

    ServerName app1.somehost.com
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

</VirtualHost>

<VirtualHost *:80>

    ServerName app2.somehost.com
    ProxyPass / http://localhost:3001/
    ProxyPassReverse / http://localhost:3001/

</VirtualHost>

Note that you must create subdomains for each applications in above way. and set MOJO_REVERSE_PROXY environment variable to 1, redirect_to method can write absolute URL right.

# Application Class
sub startup {
    my $self = shift;
    $ENV{MOJO_REVERSE_PROXY} = 1;
}

If you see apache "Service Temporarily Unavailable" error, SELinux mode is maybe set to "enforcing". This usually happens on Red Hat based Linux distributions. SELinux forbids the Apache webserver to connect to the network. There is a certain boolean variable which be set. Please run the following command to allow the Apache webserver to connect to network (even it's on the localhost).

$ sudo setsebool -P httpd_can_network_connect=1

Please note: There is no need to turn off SELinux completely.

Apache/mod_proxy (Path)

you can also do the following way using path.

<VirtualHost *:80> ServerName somehost.com <Proxy *> Order deny,allow Allow from all ProxyRequests Off ProxyPreserveHost On

ProxyPass /app1 http://localhost:3000/app1 keepalive=On
ProxyPassReverse /app1 http://localhost:3000/app1

ProxyPass /app2 http://localhost:3001/app2 keepalive=On
ProxyPassReverse /app2 http://localhost:3001/app2

RequestHeader set X-Forwarded-HTTPS "0"

If X-Forwarded-Host exists, url_for and redirect_to method can write absolute URL right. In this case not like using host name, you must set request base URL path by yourself.

$app->hook('before_dispatch' => sub {
  my $self = shift;
  if ($self->req->headers->header('X-Forwarded-Host')) {
    # Proxy Path setting
    my $path = shift @{$self->req->url->path->parts};
    push @{$self->req->url->base->path->parts}, $path;
  }
});

Apache/mod_proxy (Serving static files)

 <VirtualHost *:80>

   ServerName app.somehost.com

   # Make sure that document root points to public dir of our application
   DocumentRoot /path/to/public

   # Don't proxy any request beginning with the keyword "/static".
   # So, for example, "/static/logo.gif" will be served directly by
   # Apache from the "/path/to/public/static/logo.gif file"
   # The ! (exclamation mark) keyword in ProxyPass means "don't"
   ProxyPass /static !

   # Another one for "favicon.ico", so that explorer and mozilla are happy
   ProxyPass /favicon.ico !

   # And now we send back to our application everyting else that does
   # not begin with "/static" or "/favicon.ico"
   ProxyPass / http://localhost:3000/
   ProxyPassReverse / http://localhost:3000/

 </VirtualHost>

Apache/CGI

To make Mojolicious application run in CGI mode under Apache make sure your httpd.conf or .htaccess file looks like following:

 AddHandler cgi-script .cgi
 Options +ExecCGI

 IndexIgnore *

 RewriteEngine on

 RewriteCond %{DOCUMENT_ROOT}/public/%{REQUEST_URI} -f
 RewriteRule ^(.*) public/$1 [L]

 RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
 RewriteRule ^(.*) myapp.cgi [L] 

In this way you make Apache render static files from /public folder for you.

Pretty "Web 2.0" URLs

Nobody really likes URLs like www.mycompany.com/myapp.cgi/foo/bar. Instead we want prefer seeing: www.mycompany.com/foo/bar, they are much nicer to use. The following configuration will hide the fact that the application is running from a cgi. Particularly useful if your hosting environment forbids the use of ScriptAlias.

 ## .htaccess
 RewriteEngine on
 # Rewrite only if the request isn't for a real file, directory, or symlink.
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-l
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule ^(.*)$ myapp.cgi/$1 [L]

 ## lib/MyApp.pm
 sub startup {
      my $self = shift;
      # ... your start up and routes.
      $self->hook( before_dispatch => sub {
           my $self = shift;
           # notice: url must be fully-qualified or absolute, ending in '/' matters.
           $self->req->url->base(Mojo::URL->new(q{http://www.mycompany.com/}));
      });
 }

Apache/mod_perl (PSGI/Plack)

mod_perl is a good example for a PSGI adapter that is used without plackup, note that setting the PLACK_ENV environment variable is required for Mojolicious PSGI detection.

In shared environments with more than one VirtualHost using mod_perl PerlOptions +Parent is recommended. Otherwise there can be namespace conflicts.

<VirtualHost *:80>
  ServerName myapp.local
  DocumentRoot /home/sri/myapp

  PerlOptions +Parent

  <Perl>
    $ENV{PLACK_ENV} = 'production';
    $ENV{MOJO_HOME} = '/home/sri/myapp';
    $ENV{MOJO_MODE} = 'deployment';
  </Perl>

  <Location />
    SetHandler perl-script
    PerlResponseHandler Plack::Handler::Apache2
    PerlSetVar psgi_app /home/sri/myapp/script/myapp
  </Location>
</VirtualHost>

Apache/Shared Hosting

We have a discussion on the mailinglist about setting up mojo in shared environments.

https://groups.google.com/group/mojolicious/browse_thread/thread/6f17653fe30ab884

And here is the actual example working equally well with mod_fastcgi and mod_cgi: http://github.com/kberov/MYDLjE/blob/master/.htaccess