Thursday, October 1, 2015

Configuring Multiple Instances of ColdFusion 10+ with Apache Virtual Hosts

Note: This is a curated blog post from Rob Brooks-Bilson's old blog, which is no longer existent. Although this was written at the time of CF10's release, the same procedure applies for CF11.

You can create additional ColdFusion instances and tie them to multiple virtual hosts in Apache (the multiple virtual hosts part is often referred to as multihoming).

For the purposes of this blog post, I'm going to assume that you've already installed ColdFusion 10 in the Server Configuration (Not EAR/WAR deployment). I'm also going to assume you chose to install Apache as your web server during the install process. This gives you a single instance of ColdFusion 10 (cfusion) with Apache connected to ColdFusion as localhost.

The first thing we need to do is create our new ColdFusion instance (for this exercise, we'll call the new instance cfusion2). To do this, we need to fire up the ColdFusion Administrator. Once logged in, click on the Instance Manager link in the Enterprise Manager section. Here you'll see a list of currently configured instances. To create a new instance, click the Add New Instance button:
click to zoom

Enter cfusion2 in the Server Name box. Leave the Server Directory as is. If you're on Windows, make sure the Create Windows Service box is checked. When you're finished, click Submit.
click to zoom
It generally takes a couple of minutes for ColdFusion to create the instance. When it's finished, you'll see a screen with a link back to the Enterprise Manager. Go ahead and click the link once it appears:
click to zoom
Once you're back in the Instance Manager, you should see the new cfusion2 instance. Notice how the HTTP Port column shows 8500? This is because the new instance is setup to use Tomcat's built-in web server. Don't worry about that right now, we'll get to fixing that in just a minute. For now, just note the value in the Remote Port column for your cfusion2 instance as we'll be needing it shortly.
click to zoom
If you're wondering where ColdFusion 10 physically puts the directory structure for your instances, it's directly in the /ColdFusion10 install root:
click to zoom
Now it's time to make some changes to ColdFusion's underlying Tomcat server configuration and Apache Tomcat connector configuration. Fire up your favorite text editor and open the server.xml file located in:
C:\ColdFusion10\cfusion2\runtime\conf
About halfway down the file, you should see a line of XML that looks like this:
<Connector port="8013" protocol="AJP/1.3" redirectPort="8446" tomcatAuthentication="false">

Verify that the Connector Port matches the Remote Port you noted earlier from the Instance Manager for the cfusion instance.
At the bottom of the file, you should see some additional XML that looks like this:
<Connector port="8500" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool"></Connector>

This code is used to configure Tomcat's built-in web server. Since we want to connect our ColdFusion instance to Apache, we need to disable this. To do that, simply comment it out and save the file:
<!-- <Connector port="8500" protocol="org.apache.coyote.http11.Http11NioProtocol" connectionTimeout="20000" redirectPort="8443" executor="tomcatThreadPool"></Connector> -->

Now that we've disabled the built-in web server, we need to tell Tomcat we want to use Apache as our web server instead. To do this, we have to make some changes to the Apache Tomcat connector ColdFusion previously installed. The connector and its associated configuration files can be found here:
C:\ColdFusion10\config\wsconfig\1
The connector itself is compiled and named mod_jk.so. There's not much to do with it other than to verify that it's there. The two files that we're interested in for our instance configuration are workers.properties and uriworkermap.properties.
The workers.properties file is used to configure your server instances. If you open it up in a text editor, you'll see that it's configured for your default cfusion instance:
worker.list=cfusion

worker.cfusion.type=ajp13
worker.cfusion.host=localhost
worker.cfusion.port=8012

To add our additional cfusion2 instance, we simply have to make two changes:
worker.list=cfusion,cfusion2

worker.cfusion.type=ajp13
worker.cfusion.host=localhost
worker.cfusion.port=8012

worker.cfusion2.type=ajp13
worker.cfusion2.host=localhost
worker.cfusion2.port=8013

worker.list should contain a comma delimited list of all of the server instances you have. Below that, you need to configure the properties for each instance. You only need to concern yourself with the port here. Each ColdFusion instance gets its own port, which you can obtain from the Instance Manager in the ColdFusion Administrator.
Next, make a copy of your uriworkermap.properties file and name it uriworkermap_cfusion2.properties. The ColdFusion 10 docs tell you to rename it to uriworkermap1.properties, but I don't like that convention - especially if you have a lot of instances. Anyhow, change all of the mappings in the uriworkermap_cfusion2.properties file so that they apply to the cfusion2 instance. Here's how that should look:
/cfformgateway/* = cfusion2
/CFFormGateway/* = cfusion2
/flex2gateway/* = cfusion2
/flex2gateway = cfusion2
/cffileservlet/* = cfusion2
/CFFileServlet/* = cfusion2
/cfform-internal/* = cfusion2
/flashservices/gateway/* = cfusion2
/flex-internal/* = cfusion2
/rest/* = cfusion2
/*.cfml/* = cfusion2
/*.mxml = cfusion2
/*.as = cfusion2
/*.cfm = cfusion2
/*.cfm/* = cfusion2
/*.swc = cfusion2
/*.cfml = cfusion2
/*.cfc = cfusion2
/*.cfc/* = cfusion2
/*.cfr = cfusion2
/*.cfswf = cfusion2
/*.sws = cfusion2
/*.jsp = cfusion2
/*.hbmxml = cfusion2

That's it for the Apache Tomcat connector configuration. All that's left to do now is to setup our Apache virtual hosts, restart all of our servers and verify everything's working as expected.
Open your Apache http.conf file and notice that ColdFusion has placed the following directive at the bottom of the file:
# Load mod_jk module
Include "C:\Program Files (x86)\Apache Software Foundation\Apache2.2\conf\mod_jk.conf"

This directive tells Apache to load the mod_jk.conf configuration file that ColdFusion created when you told it to configure Apache as your web server.
Open your mod_jk.conf file and create the virtual hosts. Here's my mod_jk.conf file (I added some space and moved some things around to make it easier to read):
# Load mod_jk module
LoadModule jk_module "C:\ColdFusion10\config\wsconfig\1\mod_jk.so"
# Where to find workers.properties
JkWorkersFile "C:\ColdFusion10\config\wsconfig\1\workers.properties"
# Where to put jk logs
JkLogFile "C:\ColdFusion10\config\wsconfig\1\mod_jk.log"
# Where to put jk shared memory
JkShmFile "C:\ColdFusion10\config\wsconfig\1\jk_shm"
# Set the jk log level [debug/error/info]
JkLogLevel info
# Select the timestamp log format
JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

AddHandler jakarta-servlet .cfm .cfml .cfc .cfr .cfswf

<Files ~ ".hbmxml$">
Order allow,deny
Deny from all
</Files>

<VirtualHost *:80>
 ServerName localhost
 DocumentRoot C:/_web/cf10/cfusion/localhost/wwwroot
 ErrorLog c:/_web/logs/cfusion-localhost.log

 JkMountFile "C:\ColdFusion10\config\wsconfig\1\uriworkermap.properties"

<Directory "C:/_web/cf10/cfusion/localhost/wwwroot">
        Options Indexes FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
</Directory>

    Alias /CFIDE "C:\ColdFusion10\cfusion\wwwroot\CFIDE"

    <Directory "C:\ColdFusion10\cfusion\wwwroot\CFIDE">
        Options Indexes FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

<VirtualHost *:80>
 ServerName cfusion2.foo.com
 DocumentRoot C:/_web/cf10/cfusion2/zeus2/wwwroot
 ErrorLog c:/_web/logs/cfusion2-zeus2.log

 JkMountFile "C:\ColdFusion10\config\wsconfig\1\uriworkermap_cfusion2.properties"

<Directory "C:/_web/cf10/cfusion2/zeus2/wwwroot">
        Options Indexes FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
</Directory>

    Alias /CFIDE "C:\ColdFusion10\cfusion2\wwwroot\CFIDE"

    <Directory "C:\ColdFusion10\cfusion2\wwwroot\CFIDE">
        Options Indexes FollowSymLinks
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

For my cfusion2 instance, the single virtual host points to uriworkermap_cfusion2.properties:
JkMountFile "C:\ColdFusion10\config\wsconfig\1\uriworkermap_cfusion2.properties"

That's it for configuration. Go ahead and stop and start your ColdFusion instance and your Apache web server just to make sure all changes are reflected.
Test out the URL for your virtual host to make sure everything is pointing where it should be:
http://cfusion2.foo.com
Now open the ColdFusion Administrator on localhost:
http://cfusion2.foo.com/CFIDE/administrator
Everything should load up fine. In the Mappings section of the Administrator, /CFIDE and /gateway point to the correct locations:

For my cfusion2 instance, the single virtual host points to uriworkermap_cfusion2.properties:
C:/ColdFusion10/cfusion/wwwroot/CFIDE
C:/ColdFusion10/cfusion/gateway/cfc

Repeat the same process for your other virtual hosts, making sure the /CFIDE and /gateway mappings point to the correct locations for your instances.
That's it, you should now be configured for multiple instances of ColdFusion with multiple Apache virtual hosts.