Webserver-to-Tomcat VirtualHost copier for Railo! (v0.4.02, april 25, 2011)

Update Apr. 19, 2011: Version 0.4.01 + 0.4.02 (bug fix). Made sure that the code is run at the moment the directoryListener is initiated. Logging is now done with cflog (file named "VHostCopier"), to enable easier debugging.
Update Dec. 19, 2010: Version 0.3.02. A 'localhost' host will now always be created, even if not found in the webserver config; error message text changed at the check if multiple wildcard hosts were found.
Update Oct. 30, 2010:
Version 0.3.01. Bug fix in the display of changed sites: if a site was previously found, and now deleted, an error occured.
Update Oct. 17, 2010: Version 0.3.00. It now also copies aliases/virtual directories from Apache/IIS to tomcat :-))
Update Oct. 10, 2010: Version 0.2.8. Changed component creation from "new ...()" to createobject(), so the code can be used on Railo 3.1. Also fixed var-scoping issues in some components.

If you use Railo as your cfml server, and use Apache or IIS as your main webserver, then you must have noticed that you need to add virtualHosts in 2 places. Once in the webserver, and once in Resin/Tomcat/Jetty, or whatever the JEE engine is you are running Railo on. This approach gets a lot of complaints, because people switching from Adobe Coldfusion (ACF) never had to do this. "It just worked".
The reason it works like that in ACF, is that Coldfusion has an ingenious connector between your webserver and JRUN (the JEE engine where ACF runs on). As far as I know, this connector tells JRUN what the webroot is for every request, and what virtual mappings are there.

Now I did a lot of investigation in finding out if this ACF approach could also be used for Railo, but to no avail. There is an AJP13 Extension Proposal for the connector between Tomcat and Apache, where this approach is mentioned, but it is still only a proposal.

So I thought of another way to make sure Railo knows what virtualhosts are available: by copying all virtualhost directives from Apache/IIS to the Railo server. As you can see in the title of this post, it copies them to Tomcat. That's because Tomcat is going to be the default JEE engine for Railo.

The code

Test the webserver configuration parsing

Note: you do not need to have tomcat installed to use this test functionality. It will only try to parse your IIS/Apache configuration files.

I created code which parses the Apache/IIS config files, gets the virtualhosts out of it, creates the necessary config xml for Tomcat, and adds newly found virtualHosts directly to Tomcat by using Tomcat's host-manager.

Now I have only been able to test the parser code on 3 machines, while there are probably 100's of webserver configurations. So my question to you: please download and extract the code, and run test.cfm to see if your config files are correctly parsed.
Afterwards, please let me know if everything went fine. If an error is caught, then it can be automatically sent to me, so I can start debugging right away. But this is a setting that you control from the test.cfm file. If you don't want to directly send any errors, that's okay. Then just let me know by adding a comment here, or mail me at the supplied email address in test.cfm.

Install as a Railo extension

The copier is available as a Railo extension! It will install the full version, not the test version! So it will actually overwrite your tomcat configuration. If you already configured virtual hosts in tomcat, they will be overwritten (although a backup of the server.xml file will be created). So: use with care!

To install:

  1. Go to your Railo server administrator at http://localhost/railo-context/admin/server.cfm
  2. Go to the link Extensions > Providers, and add the URL http://www.railodeveloper.com/ExtensionProvider.cfc
  3. Now go to Extensions > Applications, and choose to install the "Webserver2Tomcat vhost copier".
  4. Follow the installation steps, and you're done!
  5. For debugging / checking what's going on with the extension, you can check the following files:
    1. Tomcat's config xml, where the <VHost> tags are added: {tomcat-install-dir}conf/server.xml
    2. Tomcat's ROOT.xml files per VHost, where the <Context> tags are added: {tomcat-install-dir}conf/Catalina/{hostname}/ROOT.xml
    3. VHost copier log, where messages, warnings, and errors are logged: {railo-root-path}/railo-server/context/gateway/webserver2tomcatVHostCopier/parserLog.log.
    4. Tomcat's host-manager, by default at http://localhost:8080/host-manager/html
    5. Railo's log files, especially DirectoryWatcher.log, exception.log, and gateway.log: {railo-root-path}/railo-server/context/logs/
    6. An event gateway (Directory listener) will be installed by the extension, you can check it out in your Railo server administrator at Services > Event gateways.

What gets installed

  • A directory listener, which looks at the webserver configuration file(s) every 4 seconds, and triggers the VHost-copier when a change occurs.
  • The VHost copier source code, which is used by the directory listener.

What the code does

Before the code can run, a config file must be created. This is done by the Extension installer, or by maually editing it from the test.cfm file.
The config file needs to know:

  • what type of webserver you use
  • where Apache's httpd.conf is located (if using Apache)
  • where tomcat is installed, and on which port it runs
  • login info for the tomcat host-manager

Then, the following steps are done:

  1. The parser reads the config file
  2. Parses the webserver configuration to retrieve all virtualhosts
  3. Checks if there are any changes in the virtualhost (by looking at a backup file of the previously retrieved virtualhosts).
    Note: this backup file is not created when using the test.cfm file.
  4. Creates the necessary <VHost> tags for all the virtual hosts, and writes them to Tomcat's server.xml file (overwriting any existing <VHost> tags)
  5. Creates/deletes an xml file for every changed host, where the <Context docBase="{web-root-directory}" /> is written. These files are created in {tomcat-install-dir}conf/Catalina/{hostname}/ROOT.xml.
  6. Every newly found and deleted virtualHost is directly added to Tomcat by using the Tomcat host-manager. Otherwise, tomcat would only pickup the new VHosts after a restart.
  7. A backup file is created which contains info about the current virtualHost data.

Requirements (for the full version)

  • The tomcat hostmanager must be enabled and running. Check this by going to http://localhost:8080/host-manager/html (or your own custom tomcat port)
  • You must have a valid user for the host-manager. You can add a user by editing the file {tomcat installation directory}/conf/tomcat-users.xml to contain the following:
    <tomcat-users><role rolename="manager"/><role rolename="admin"/><user name="SOME NAME" password="SOME PASSWORD" roles="admin,manager"/></tomcat-users>
  • createObject() function and <cfinvoke> tag must be allowed (not sandboxed)
  • Railo must have read access to the Apache or IIS config files
  • Railo must have write access to Tomcat's server.xml file, and the directory {tomcat-install-dir}/conf/Catalina/

Limitations

I have not yet taken a look at the IIS-to-tomcat ISAPI filters,  so I am not sure if you need to do some extra configuration within IIS to map cfm and cfc files to be handled by Tomcat.

In Apache and IIS, you can have the webserver listening to different ports and ip addresses, for the same hostname. If you have multiple virtualhosts which have the same hostname, but use a different webroot, then this VHostcopier won't work. This is because Tomcat only checks the hostname, not the listening port or ip address.
An example Apache configuration where this happens is:

<VirtualHost *:80>
DocumentRoot /websites/mysite.com/
ServerName www.mysite.com
</VirtualHost>
# SSL website, pointing to another webroot, but with the same hostname:
<VirtualHost *:443>
DocumentRoot /websites/securestuff.mysite.com/
ServerName www.mysite.com
</VirtualHost>

So you read the whole article? Great!

Would you then please also take the time to test this code? And let me know what happened? Great!

del.icio.us Digg StumbleUpon Facebook Technorati Fav reddit Google Bookmarks
| Viewed 15437 times
  1. Jonathan van Zuijlekom

    #1 by Jonathan van Zuijlekom - October 7, 2010 at 10:23 PM

    We use Railo with Apache and Tomcat and I'm so clad you made this. I have made a script to add the vhost from apache to the Tomcat, but you still need to restart Tomcat. I have looked at the host manager, but didn't find what I needed.

    I'm gonna test this and get back to you.
  2. Jonathan van Zuijlekom

    #2 by Jonathan van Zuijlekom - October 7, 2010 at 10:58 PM

    Paul,

    You used the New operator in your soure. This New operator is only available from version 3.1.2.013 onwards. As we use the latest stable production version (3.1.2.001).

    I'm gonna rewrite those to createObject tomorrow and get back to you.
  3. Sean Daniels

    #3 by Sean Daniels - October 7, 2010 at 11:01 PM

    Hi Paul, the error you probably just got (file or directory /etc/apache2/apache2.conf not exist) was from me. As I explained on the Railo list I am running Tomcat (and therefore test.cfm) from a separate machine than Apache. So I believe the error can be fixed by me making /etc/apache2/apache2.conf readable to the Tomcat server. No more time to play with this today, but I will try again soon...
  4. Paul Klinkenberg

    #4 by Paul Klinkenberg - October 8, 2010 at 11:12 PM

    Hi Jonathan, yes, I indeed use the new operator. In the near future, this code is hopefully used for new Railo installs, and they will be on Railo 3.2. Sorry to hear that's a problem for your setup; I hope you can easily manage to change that code?
    Thanks for testing, and let me know how it went!

    @Sean: please try again soon :-)

    Paul
  5. Jonathan van Zuijlekom

    #5 by Jonathan van Zuijlekom - October 8, 2010 at 11:19 PM

    I'll just upgrade my dev box to the latest development version and test is with the production apache2 config files.
  6. Bilal Soylu

    #6 by Bilal Soylu - October 13, 2010 at 7:36 PM

    Paul,
    this looks very promising, I wonder whether a similar approach could be used in the Linux/OSX installers rather than trying to do all in installer based coding.
  7. Paul Klinkenberg

    #7 by Paul Klinkenberg - October 15, 2010 at 1:46 PM

    Hi Bilal, I think that we could just simply edit the Apache httpd.conf with the installer, copy the necessary mod_jk connector, then (if requested) edit the railo-server.xml file to include this vhost-copier, and then we could already be done :-)

    Good idea?
    Paul
  8. Paul Klinkenberg

    #8 by Paul Klinkenberg - October 15, 2010 at 1:52 PM

    Hi Jonathan, I posted a new version of this code, which should be compatible with Railo 3.1. If you, AND OTHERS, could take the time to do this testing, great!
    Untill now, I have received zero tests back :-/
    Thanks in advance, Paul
  9. Hendrik Kramer

    #9 by Hendrik Kramer - December 3, 2010 at 1:21 PM

    Hi,

    using Railo 3.2.003 and IIS7 on Windows, the parser found the entries I entered previously manually, but struggles on the new ones from IIS7:

    Same host found twice, with different webroots! Host=localhost, path1=%SystemDrive%\inetpub\wwwroot\ROOT, path2=d:\Internet\cfa_garm

    and many more.

    The applicationHost.config for this web:
    <site name="[53] Garm" id="10">
    <application path="/">
    <virtualDirectory path="/" physicalPath="d:\Internet\cfa_garm" />
    <virtualDirectory path="/jakarta" physicalPath="C:\Tomcat6\connector" />
    </application>
    <bindings>
    <binding protocol="http" bindingInformation="10.10.3.53:80:" />
    </bindings>
    </site>

    The URL should be http://10.10.3.53/ and not localhost. Any hints? I'm using the current version 0.3.01
  10. Jon Cavanaugh

    #10 by Jon Cavanaugh - January 5, 2011 at 9:21 PM

    When trying to run Railo under a specific account (lets say: railouser) and if there is a domain that does not grant the "railouser" rights, the Railo Administrator page crashes with this error. Is there a way to exclude certain sites from being added to Tomcat?

    javax.servlet.ServletException: static path [/WEB-INF/railo/] for servlet init param [railo-web-directory] is not allowed, path must use a web-context specific placeholder.

    Enviroment: IIS7, Tomcat/Railo installer.
  11. Jon Cavanaugh

    #11 by Jon Cavanaugh - January 5, 2011 at 11:23 PM

    Second question, is it possible to disable the CreateObject JAVA for all sites but a specific context that run the Vhost Copier?

    Thanks,

    Jon C.
  12. Paul Klinkenberg

    #12 by Paul Klinkenberg - January 20, 2011 at 1:58 PM

    Hi Jon, sorry for the slow response. I just became a father 2 weeks ago, so I'm pretty busy (and happy)!
    So, you are running Tomcat with Railo under the 'railouser' login, right? The Railo error you get should be a more specific one, but is indeed because the user does not have rights to create the WEB-INF folder.
    You could create a workaround for your specific problem by editing the file Webserver2TomcatVHostCopier.cfc. If you add a try-catch within (not around) the cfloop at comment "now de/activate the new and deleted hosts by using the Tomcat host-manager", these errors will be caught, and the script can continue.
    At every tomcat startup, you will see the same error in the log, but it will nevertheless startup correctly.

    "possible to disable the CreateObject JAVA": yes, you can fix this by going to the Railo server admin > Security > Access, and uncheck "Tags and functions > Tag CFObject / function CreateObject".
    After saving, click on the tab "Individual" on that page, and then check this checkbox for the web context you are running the vhost copier on.

    Hope it helps, cheers, Paul
  13. Jon Cavanaugh

    #13 by Jon Cavanaugh - January 20, 2011 at 2:34 PM

    Paul,
    Congratulations, on the new child!

    Thanks for following up, the Vhost copier is installed at the "global" level (server administrator) so I'm not sure which "context" you would consider that installed under. I'm guessing localhost?

    Oh and I will see about the cftry within the cfloop.

    Jon Cavanaugh
  14. Jon Cavanaugh

    #14 by Jon Cavanaugh - January 20, 2011 at 5:07 PM

    Paul,
    How does the vhostcopier handle when new aliases are added to a domain. I can't find how to add a domain alias in the tomcat manager? I would like to avoid restarting the tomcat server, such is one of the main reasons for the vhostcopier.

    Thanks,

    Jon C.
  15. Paul Klinkenberg

    #15 by Paul Klinkenberg - January 20, 2011 at 8:23 PM

    Jon, in tomcat, the domain aliases are added as new hosts, just like a regular virtual host. Cheers, Paul
  16. Bilal

    #16 by Bilal - March 25, 2011 at 1:57 PM

    Paul,
    I foolishly went through the work of creating a new connector between Tomcat and IIS.
    http://tomcatiis.riaforge.org
    It still used the AJP1.3 channel but also makes some additional enhancements. E.g. it guesses at flush/cfflush, adds basic security, adds threats more quickly etc.
    I am wondering whether, as enhancement, I could detect changes to IIS setup (e.g. added hosts and call your host copier). This would probably more efficient than attempting to do things on a scheduled basis etc.
  17. Paul Klinkenberg

    #17 by Paul Klinkenberg - March 25, 2011 at 3:45 PM

    Hi Bilal,
    This is absolutely great news, a native AJP connector for IIS! I did not even know you were working on this, but I see a lot of options :-))
    It would definitely be a great improvement, if the vhost copier is just called on-demand instead of as a scheduled task.

    The only thing left to do for me, is to think of a url you can call from the connector. Which is a tricky choice, since users can/will change the root for the localhost. Maybe I could add the vhost copier code to {tomcat-root}/webapps/host-manager/, which is an awfull hack, but that webapp must exist for the vhost copier to work, and is always available... And is by default already secured to only allow calls from 127.0.0.1.
    Is that an idea for you, just calling a url?

    Once again: great work, this will be a major leap forward!

    Cheers, Paul
  18. Paul Klinkenberg

    #18 by Paul Klinkenberg - March 25, 2011 at 3:52 PM

    Hi Bilal,

    One more thing... If you add the option of calling URLs from your connector anyway, then you could also just call the tomcat host-manager, to add the web context on the fly!
    That would mean: no more vhost copier, and ultimate flexibility.
    If you can somehow keep records of which hostname+rootdirectory you already added to the host-manager, then only the 1st call to a website will be slow.

    There is one downturn though: IIS mappings/aliases would not work this way. I'm not sure if you can add them via the host-manager as well...

    Anyway, we'll see ;-) Paul
  19. Paul Klinkenberg

    #19 by Paul Klinkenberg - April 19, 2011 at 6:11 PM

    To whom it might concern: the VHost copier has been updated to 0.4.01 :-)
  20. Sam

    #20 by Sam - May 31, 2011 at 12:49 PM

    Hi Paul
    Have been wanting this kind of functionality, owww, id say for the past 3 years! We've installed the extension under Railo 3.2.2 - just looking at how to use it now. Will advise of our progress. End goal is to automate the setup and control of Railo/Tomcat hosts from mysql db. Best, Sam
  21. Russ

    #21 by Russ - August 2, 2011 at 10:05 PM

    Hi Paul,

    I have tested your plugin on a couple of IIS7 servers, and while it creates the vhost entries, they are missing the path to the webroot.

    e.g.



    <Host name="myhostsupport.com" appBase="webapps" unpackWARs="true" autoDeploy="true" xmlValidation="false" xmlNamespaceAware="false" />

    It also seems that additional host headers should be added as aliases rather than separate vhosts.
  22. Paul Klinkenberg

    #22 by Paul Klinkenberg - August 2, 2011 at 10:14 PM

    Hi Russ, thanks for checking the code out!
    The answer to your question is in this blog post, section "What the code does", point 5.

    Regards, Paul
  23. Russ

    #23 by Russ - August 2, 2011 at 10:27 PM

    HA! sorry that will teach for not reading.
    I obviously have some other problem then.
  24. Paul Klinkenberg

    #24 by Paul Klinkenberg - August 2, 2011 at 10:28 PM

    Yeah, well, it is a pretty dry piece of text to read, I know :-/
  25. Snake

    #25 by Snake - August 18, 2011 at 12:26 AM

    I just installed your plugin on a live production server.
    It had 200 or so sites on it, which resulted in 600+ vhost entries including aliases.
    This totally killed Railo/Tomcat and caused 100% cpu usage and resulted in the heap running out of memory.
    Restarting Tomcat immediately resulted in 100% cpu usage again, and I had to delete all the vHosts to get things back to normal.

    Just thought you might like to know.
  26. Paul Klinkenberg

    #26 by Paul Klinkenberg - August 18, 2011 at 11:22 PM

    Hi Russ, well, that's interesting info indeed. Too bad it was discovered the way it was :(
    I will take this into account when developing the next release version.
    This is a tomcat thing btw, not Railo.

    Thanks, Paul
  27. Todd Rafferty

    #27 by Todd Rafferty - August 19, 2011 at 1:59 AM

    Russ, why would you not test this on another server first before running it in your production environment? o_O I'm talking about another server with 600 entries. Mimicking your production server as much as possible so you know what to expect?
  28. Russ

    #28 by Russ - August 19, 2011 at 2:03 AM

    I do not have a non production server with this many sites on it, and Railo was already broken anyway, I was reinstalling it using it Tomcat, so nothing to lose.
    As it goes I could not get Railo working and had to switch to Coldfusion anyway.
  29. Russ

    #29 by Russ - August 19, 2011 at 2:05 AM

    Also Todd, I am just making Paul aware of this issue as he is the developer of this plugin, not having a go or blaming him.
  30. Todd Rafferty

    #30 by Todd Rafferty - August 19, 2011 at 2:59 AM

    Understood, but you don't need a real server with 600 sites. You need a server that's close to what you're running and a httpd.conf with 600 entries for testing. Quick question, you switched back to ACF, did you ever consider getting consulting from Jordan or even the Railo team to get things working?
  31. Russ

    #31 by Russ - August 19, 2011 at 3:07 AM

    Yes Jordan tried to help but we didn't have any luck and I tried contacting Railo team. I'm sure I could have got it working eventually, but I needed to get sites back online ASAP.
  32. Todd Rafferty

    #32 by Todd Rafferty - August 19, 2011 at 3:12 AM

    Thanks, I was just curious.
  33. Jason

    #33 by Jason - November 18, 2011 at 7:46 PM

    Hello, I'm trying to use the installer via Railo Applications and I get as far as Step 3, and I get the following error:

    you have no access for action [server.updategatewayentry]

    error occured in Install.cfc:173
    171: , deleteFunction="startWebserver2TomcatVHostCopier"
    172: }#'
    173: readOnly=false
    174: />
    175:

    I'm certain I have the TomCat users and roles setup, and I'm sure I have the correct port for the tomcat manager. I would really love to get this working. Any help is appreciated!

    Setup: Railo 3.3 Windows 2008 R2, IIS 7.5
  34. Paul Klinkenberg

    #34 by Paul Klinkenberg - November 18, 2011 at 8:54 PM

    Hi Jason, I am sorry I haven't updated this blog post!
    Problem is that Railo removed the event gateways from the server admin in version 3.3.
    Therefor, the installer doesn't work correctly atm :-(

    What I will do in a short while, is change the installer to be used from a web admin. That's only an intermediate solution, since we wouldn't want this heavy functionality to be installed by any web admin user, but it's the best I can do atm.

    I will get back to you when I changed the installer, okay?

    Once again, sorry for the lack of info!

    Paul
  35. Jason

    #35 by Jason - November 18, 2011 at 8:59 PM

    Thanks Paul for your quick reply. Is it still possible to install this manually in Railo 3.3? Or should I just wait until you get around to creating an installer ?
  36. Paul Klinkenberg

    #36 by Paul Klinkenberg - November 18, 2011 at 9:24 PM

    Well, I hope to have the installer fixed by tonight ;-)

    Paul
  37. Jude

    #37 by Jude - December 5, 2011 at 12:47 AM

    Hi, did you manage this done, or is it still broke in current version of railo ?
  38. Paul Klinkenberg

    #38 by Paul Klinkenberg - December 5, 2011 at 9:39 AM

    Hi Jude,

    I released a new version of the VHost copier a few days ago :)
    You can install it from your Railo WEB admin (instead of the server admin).
    The specifications are the same as written in this blog post, with the exception that "event gateways" have been removed from the server admin in Railo 3.3, which made the installation of this extension impossible.
    So I had to switch to a WEB admin install, to be able to use the event gateway again.

    To install, just go to one of your Railo web admins (choose a site which will not be removed), and then go to Extensions > Applications, and click on "VHost copier".

    Good luck, Paul
  39. Jude

    #39 by Jude - December 5, 2011 at 1:45 PM

    that's excellent.
    can I make a suggestion/feature request.
    currently this tool imports ALL sites, regardless of whether they use Railo or not, and I see from previous posts this can cause a problem if there is a lot of sites. Would it be possible to do selective/manual site imports instead. So your tool shows a list of sites in IIS/Apache, and I can choose the ones I want to import to Tomcat.
  40. Jonathon Lucas

    #40 by Jonathon Lucas - December 7, 2011 at 6:31 PM

    Hey Paul,
    Trying to install your vhost copier on a brand new Railo server using apache connectors with tomcat. Everything on Railo & Apache is working but when I go to use your installer on step 3/3 and enter the details I get this error:

    you have no access for action [server.updategatewayentry]

    error occured in Install.cfc:173
    171: , deleteFunction="startWebserver2TomcatVHostCopier"
    172: }#'
    173: readOnly=false
    174: />
    175:

    Any help would be great! :)
  41. Paul Klinkenberg

    #41 by Paul Klinkenberg - December 7, 2011 at 8:57 PM

    Hi, as you could read in previous comment, but not in the blog post itself (yet), there is a new version, which is installable from the web administrator.
    If you run into any troubles with that, let me know!
    Paul
  42. jude

    #42 by jude - January 25, 2013 at 1:35 PM

    I have had this plugin installed in the past, but have since disabled it because having RAILO created/enabled on every single site was causing problems.
    In the Railo server admin is shows as not installed, under my web admin it shows as not installed.
    But it is still running, all the folders in C:\railo\tomcat\conf\Catalina keep getting created again as does the web-inf folder in each site.

    Yes Railo/Tomcat has been restarted since it was uninstalled.

    How do I stop it ?
  43. Paul Klinkenberg

    #43 by Paul Klinkenberg - January 25, 2013 at 1:52 PM

    Hi Jude,

    So I created something that went out of control ;-)
    I assume the event gateway is still running on the machine. Go to the Railo WEB admin of the website where you initially installed the vhostCopier, and then go to Services > Event gateways.
    If you see an entry for the vhostCopier there, just remove it. You might need to stop it first; event gateways in Railo can be very stubborn, and just don't want to get deleted...

    If that doesn't help, let me know!
    Cheers, Paul
(will not be published)
Leave this field empty