Apache2 Reverse Proxy, why does my solution never match the example? - grails

I need to make a reverse proxy back to a tomcat server running a grails application.
I have always seen reverse proxy examples like this:
ProxyRequests Off
ProxyPass / http://localhost:8080/appname/
ProxyPassReverse / http://localhost:8080/appname/
ProxyPreserveHost On
In all my apps though, when I do that the page comes up and my statics get loaded like this with the context:
/appname/static/[jsapp.js][mycss.css]
so consequently styling and functionality are lost. So my workaround is has been to do this:
ProxyRequests Off
ProxyPass /appname/ http://localhost:8080/appname/
ProxyPass / http://localhost:8080/appname/
ProxyPassReverse /appname/ http://localhost:8080/appname/
ProxyPassReverse / http://localhost:8080/appname/
ProxyPreserveHost On
which I guess is a reverse-reverse-proxy; either way it seems hacky and has (what i think is) a side affect; it creates the URL with the tomcat context in it: http://servername.com/appname/user/username instead of http://servername.com/user/username. I would much prefer the later if its possible without losing the styling.
NOTES:
When i go to the base URL:http://servername.com it works fine, any link i click on after that puts the "/appname/" name in the URL.
I believe that I could resolve this by making the app on tomcat the ROOT app, however, I would prefer not to.
This example is using HTTP, I normally use AJP protocol, but I tried HTTP last just for kicks
This is in a NameVirtualHost configuration.
Apache 2.2.15, Tomcat 7.0.27, CentOS release 6.2 (Final), java version "1.7.0_04", Grails 2.0.4
Any thoughts on what I need to be doing differently?
Thanks.

There are several ways, how to solve this situation. I am using vhosts inside TomCat, so I eliminate the application name in the URL. Add this to your server.xml
<Host name="myapp.com" appBase="myappbase" unpackWARs="true" autoDeploy="false">
<Alias>www.myapp.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="myapp_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
<Context path="/thumbnails" docBase="/var/www/myapp/thumbnails" reloadable="true">
</Host>
in your $TOMCAT_HOME create a directory "myappbase", where you upload your application WAR as ROOT.war. Your application is available via http://myapp.com:8080/.
Your proxy configuration is than very simple ;-) You can also make more vhosts in 1 TomCat.
In the aforementioned configration is also an directory alias (thumbnails), which is accessible via http://myapp.com/thumbnails/ and you can use it in GSP via:
${ resource( dir: 'thumbnails', file: 'image01.png' ) }
And the last point, which can help you is setting a "static" directories in UrlMappings.groovy. These directories are ignored when translation URL to controllers and vice versa:
static excludes = [
'/css*', '/js*', '/thumbnails*'
]

Related

Apache + PHP-FPM Set proxy timeout only to specific path

I have Apache 2.4 with PHP 5.5 without using php_mod but with PHP-FPM and mod_proxy_fcgi, so I added the following to the vhost:
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:7000/home/var/www/site/$1
This worked well but when I had some problems with timeouts I added the following code in order to fix this issue to the vhost file:
<Proxy fcgi://127.0.0.1:7000>
ProxySet timeout=3600
</Proxy>
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:7000/home/var/www/site/$1
However, I would like to add this timeout only to the administration panel of the website, which is www.site.com/admin/xxx. I tried to add the location tag like below, but it didn't worked (Apache fails when restarting).
<LocationMatch ^/admin/.*\.php(/.*)?$>
<Proxy fcgi://127.0.0.1:7000>
ProxySet timeout=3600
</Proxy>
</LocationMatch >
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:7000/home/var/www/site/$1
First of all, is that possible? Then which would be the correct syntax?
Many thanks for your time
Just use the Proxy wildcard with /admin/*
While this will allow ANY script beneath admin to run with the settings defined, behind an admin (and I assume login) wall, it shouldn't be an issue.
<Proxy "fcgi://127.0.0.1:7000/home/var/www/site/admin/*">
ProxySet timeout=3600
</Proxy>
Use ProxySet outside of a Proxy directive
ProxySet within a Proxy directive can be used without defining the url/balancer/worker. But, you should still be able to use ProxySet within a Location directive.
<LocationMatch ^/admin/.*\.php(/.*)?$>
ProxySet "fcgi://127.0.0.1:7000" timeout=3600
</LocationMatch>
If apache is still failing on startup, check the apache logs, or run strace -Ff apachectl start to find the problem, it may just be a bug in that version of apache.
However, I strongly suspect your LocationMatch regex ^/admin/.*\.php(/.*)?$ to be the cause of the apache failure.

How to use geminabox with Apache web server

I want to use geminabox with Apache web server. I have searched a lot on web but could not find any concrete information. Can some one please let me know how to do this ? Will appreciate detailed suggestions.
An easy way to use Geminabox with Apache is to configure a HTTP Reverse Proxy.
For this configuration, you just need two files:
1) The config.ru just like the example in the README.md file in the geminabox repository:
require "rubygems"
require "geminabox"
Geminabox.data = "include here the data path"
run Geminabox::Server
To run the server use rackup command. This will start the server in the 9292 port. If you want to change the port number use rackup -p XXXX.
2) In the Apache side, make sure that you have the mod_proxy and the mod_proxy_http installed. If yes, just include the following lines into your Apache config file:
ProxyRequests Off
ProxyPass / http://localhost:9292/
ProxyPassReverse / http://localhost:9292/
Restart the Apache and it is done!
geminabox is a ruby application, and just like all ruby applications, Apache does not support them out of the box.
With that said, a simple Google of how to use ruby applications with Apache lead me to this, which lead me to this. I have no experience with this tool. However, it is suggested by the rails team, so it has to have some merit.
I did work with Apache VirtualHost.
In folder /etc/httpd/conf.d/ create a file gems.conf, so add it to the file:
<VirtualHost *:80>
ServerName gems.mydomain
ServerAlias gems.local
DocumentRoot /var/railsapps/gems/public
</VirtualHost>
Where /var/railsapps/gems is the folder that have the config.ru.
The domain gems.mydomain must be in your DNS or /etc/hosts

Proxy requests to virtual host in by path prefix

I'm running multiple Rails applications on TorqueBox. Each application is mounted on a different web context, e.g., localhost:8080/app1 and localhost:8080/app2 (configured via TorqueBox). Apache is configured to accept requests to app1.domain.com and app2.domain.com via virtual hosts. However, I'm running into problems where some application paths (form submission paths and others) expect to be preceeded by /app1, e.g., http://app1.domain.com/app1/rest/of/path instead of the correct http://app1.domain.com/rest/of/path.
How can I configure Apache so that the requests to http://app1.domain.com/app1/... are made to the correct path (i.e., without the leading /app1)? I've tried doing this with redirects but that doesn't work since they force a GET request and the POST data is lost in the process.
This is my current Apache config:
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
ProxyRequests Off
ProxyPreserveHost On
NameVirtualHost *:80
<VirtualHost *:80> # There are multiple vhosts like this one, for different apps.
ServerName app1.domain.com
ProxyPass / http://127.0.0.1:8080/app1/
ProxyPassReverse / http://127.0.0.1:8080/app1/
</VirtualHost>
I solved this problem by using a web host instead of a web context in the TorqueBox configuration. After that, getting the Apache configuration to work was no problem since different apps were not under specific context paths.
So, instead of this (in config/torquebox.rb):
TorqueBox.configure do
web do
context '/app1'
end
end
You should do this:
TorqueBox.configure do
web do
host 'app1.domain.tld'
end
end

jRuby deployment into a subfolder in Tomcat

While developing a jRuby application using webbrick as the webserver, all my code is written with http://localhost:3000 as the root.
When deploying to Tomcat, I create a WAR file and it creates a subfolder under the webapps/ folder: localhost:8080/project_name/
This causes a load of problems with my code. Is there anything I can do in my ruby routes.rb file to deal with this?
Should I resort to using some sort of virtual host in Tomcat?
Although this question is quite old, we ran into a similar problem with a current project of ours. The project is done with JRuby on Rails, using Tomcat 6.x (7.0.26 in development for testing purposes), needing multiple deployments of the same application on the same servlet container, having individual server names. It took me quite some time to find a good enough solution and I like to share it with you.
Continue reading, if root context is no option for you (as cosmikduster described it above). If it is, use it.
TL;DR
Use virtual hosts for each app provided by Tomcat to give yourself root context for individual apps deployed on the Tomcat servlet container. The explanation provided below is based on this and is just an illustrative example with a step by step solution attached.
The problem
The problem arises when deploying a *.war file to Tomcat, as per default, the deployed app, let's call it awesome_app_uno for now, will live under http://localhost:8080/awesome_app_uno. This is all fine and dandy but can cause problems with the internal path generation of rails, which by default will now use /awesome_app_uno for every path generated.
Explanation & initial setup
Now, JRuby Rack, which is the rack implementation for JRuby is kind enough to include a feature that automatically sets the relative_url_root for you, I quote from the README:
The Rails controller setting ActionController::Base.relative_url_root is set for you automatically according to the context root where your webapp is deployed.
Normally, I would cheer - but in the real world, we'd probably do not want something like this, as we'll have something like a proxy to get ourselves some nice domainname, e.g.
http://awesomeappuno.com/
And now we're screwed. If we take a naive solution for this, we'd probably end up using an Apache (or an nginx, whatever you like) to function as a proxy. We'll want something like
http://awesomeappuno.com/ -> http://localhost:8080/awesome_app_uno
Just for the fun of it, lets look at the configuration for an apache config file:
<VirtualHost *:80>
ServerName awesomeappuno.com
ErrorLog /var/log/apache2/awesomeappuno_error.log
LogLevel warn
CustomLog /var/log/apache2/awesomeappuno_access.log combined
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPreserveHost On
ProxyRequests off
ProxyPass / http://localhost:8080/awesome_app_uno
ProxyPassReverse / http://localhost:8080/awesome_app_uno
</VirtualHost>
Kindly stolen from here.
The madness
With that being your configuration, you can now visit http://awesomeappuno.com.
This is where you'll notice, that despite now having a clean root without prefixes, Rails will still generate paths with the /aweseome_app_uno prefix, i.e.
http://awesomeappuno.com/awesome_app_uno/the/path/you/wanted
This is generally undesirable. While some of you could propably live with this, I couldn't. Moreover, there's awesome_app_dos coming up on the horizon which needs to be deployed on the same Tomcat instance, needing it's own domain name http://awesomeappdos.com, along with the two ugly cousins awesome_staging and awesome_integration behind it. The gist is, if you're forced to use the same Tomcat container for all these apps, giving on app root context is not really an option.
You can try some solutions like writing custom initializers, resetting the ENV hash, which gets initially filled by the jruby-rack (see comments and answers above). You might find yourself rewriting the paths manually or using absolute urls. Or you create hacks for a single environment. Or you could try to use rewrites. Or mod_subsitute. You could even try using multiple tomcat instances running everything under root context.
Don't do that.
Please.
Virtual Hosts to the rescue
While reading up on the issue (and trying everything described in the last paragraph), I stumpled on an entry in the ruby forum.
You can create virtual hosts with Tomcat, providing a root context for each app. To get more in depth knowledge, you can start here or here. In short, suppose your Tomcat (7.x) is located under /usr/local/tomcat, this would be the quick and dirty version:
Create a virtual host
The host will have it's appBase within the tomcat installation for this. If this isn't your stale, change it.
(cd /usr/local/tomcat/libexec)
I am using an installation via homebrew here, I am on a mac under OSX 10.7.4 - however with slight alterations this should work on a standard Debian as well.
Open up conf/server.xml and within the engine tag create another host:
<Host name="awesome_app_uno" alias="awesomeappuno" appBase="awesome_app/uno" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false">
<Context path="" docBase="ROOT"></Context>
</Host>
After that, create a file called conf/Catalina/awesome_app_uno/ROOT.xml. These are the contents:
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="${catalina.base}/awesome_app/uno/ROOT.war">
</Context>
Afterwards, place the awesomeappuno.war as /usr/local/tomcat/libexec/awesome_app/uno/ROOT.war and restart Tomcat. You can check the virtual host via http://localhost:8080/host-manager/html.
You should be able to visit http://awesome_app_uno:8080 and find your app there. Paths should now be correct, however, port 8080 isn't that user friendly. With slight changes to the previously shown apache config, we can also get a nice name for this:
<VirtualHost *:80>
ServerName awesomeappuno.com
ErrorLog /var/log/apache2/awesomeappuno_error.log
LogLevel warn
CustomLog /var/log/apache2/awesomeappuno_access.log combined
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPreserveHost On
ProxyRequests off
ProxyPass / http://awesome_app_uno:8080/
ProxyPassReverse / http://awesome_app_uno:8080/
</VirtualHost>
Reload your apache and you should now have no further problems with pathing, routing, because everything now happens under the root context of the tomcat virtual host.
Rinse and repeat for additional apps on the same tomcat instance.
The end
Hope i could help you with this.
lg,
flo
There is code in JRuby-Rack to deal with this. Depending on the version of Tomcat and/or Rails, it may not be detecting the extra context path correctly.
The environment variable that is supposed to take effect is called ENV['RAILS_RELATIVE_URL_ROOT']. You might print out the value of that expression during boot time and see whether it's getting set when you run in Tomcat.
The code in question is here:
https://github.com/nicksieger/jruby-rack/blob/master/src/main/ruby/jruby/rack/rails.rb#L32-38
The versions of Tomcat, Rails and JRuby-Rack you're using would help diagnose the problem further.
Your app should almost never care about the host/domain/port it will run under. To deploy at the relative path /, instead of /myapp, simply rename the WAR to ROOT.war instead of myapp.war when you copy it to the tomcat/webapps folder.

Configuring Ruby On Rails App in a subdirectory under Apache

I've got apache2.2 on windows. I'm trying to serve both subversion (/svn) and redmine (/redmine). I have svn running fine with this config:
<Location /svn>
DAV svn
SVNParentPath C:/svn_repository
...
</Location>
This is working great--my svn users can hit http://mybox/svn just fine.
Now I want to add another directory for a rails app (RedMine):
I followed the advice in this question to setup a mongrel server and have apache proxy clients through to it. It works fine if I make it the root--but I'm having trouble making it in a subdirectory:
<Location /redmine>
ProxyPass http://localhost:3000/
ProxyPassReverse http://localhost:3000/
</Location>
Any suggestions?
Here's what I had to change:
I removed the trailing slash:
<Location /redmine>
ProxyPass http://localhost:3000
ProxyPassReverse http://localhost:3000/
</Location>
And in my rails app:
# added to end of file C:\redmine\config\environment.rb
ActionController::AbstractRequest.relative_url_root = "/redmine"
Now it's working!
I wasn't completely happy with this approach--I ran into some redirect issues. This is another attempt which seems to be working well so far.
Fast CGI and Fast CGI without VirtualHosts
Tuning Fast CGI
This second approach seems better.
UPDATE:
As noted in the comments, for more recent apps running on Rails 2.3.2+, use this instead:
config.action_controller.relative_url_root = '/redmine'
I put it in the new additional_environment.rb file.
In case you still wish to use Mongrel + Apache using a reverse proxy here is how I solved the same issue on our system (Win2k3, Apache 2.2, trunk of Redmine). The secret is to install your mongrel service using --prefix /redmine which tells it to serve it from http://localhost:port/redmine
In Apache httpd.conf (or suitable include file):
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
<IfModule mod_proxy.c>
ProxyRequests Off
#No need to forward on static content - let apache do it faster
ProxyPass /redmine/images !
ProxyPass /redmine/stylesheets !
ProxyPass /redmine/javascript !
# Remove the following entry on public sites as this is insecure
ProxyPass /redmine/plugin_assets !
ProxyPass /redmine/help !
ProxyPass /redmine http://localhost:4000/redmine
ProxyPassReverse /redmine http://localhost:4000/redmine
ProxyPreserveHost On
#continue with other static files that should be served by apache
Alias /redmine/images C:/Repositories/redmine/public/images/
Alias /redmine/stylesheets C:/Repositories/redmine/public/stylesheets/
Alias /redmine/javascript C:/Repositories/redmine/public/javascript/
# Remove the following on public sites as this is insecure
Alias /redmine/plugin_assets C:/Repositories/redmine/public/plugin_assets/
Alias /redmine/help C:/Repositories/redmine/public/help/
</IfModule>
# Make sure apache can see public and all subfolders - not suitable for public sites
<Directory "C:/Repositories/redmine/public/">
Allow from all
Order allow,deny
</Directory>
Mongrel is installed as such:
mongrel_rails service::install --prefix /redmine -N redmine_prod -p 4000 -e production -c C:\Repositories\redmine
Hope that helps someone. Initially, I tried setting up Apache + fastcgi etc but I lost more precious hair - it's not Windows friendly.
P.s. I found this PDF a very useful referene: http://www.napcsweb.com/howto/rails/deployment/RailsWithApacheAndMongrel.pdf
/Damien
Passenger (http://modrails.com) is a better alternative to fastcgi because it's very easy to configure I would recommend using this for hosting your rails apps using a similar configuration to what you have now
I agree with Radar. Passenger is really easy to set up, lets Rails apps share memory, removes the burden of managing a cluster of mongrels and requires virtually no configuration. All you need are a special 'config.ru' file with a RackUp config and a DocumentRoot pointing to RAILS_ROOT/public set in Apache.

Resources