Mod_cfml supported added to CommandBox bleeding edge

For anyone who’s been kept away from CommandBox because you have a ton of virtual hosts and don’t want to have just as many separate CommandBox servers, this feature is for you. Please help me test it before it releases!

https://ortussolutions.atlassian.net/browse/COMMANDBOX-1411

Traditional CommandBox servers have only a single web root, so if you run an Saas setup where you have 200 separate web roots in IIS, CommandBox wasn’t a very tenable solution for you since it would be a waste of resources to start 200 servers. With the addition of support for multiple contexts, you can now stick a single CommandBox instance behind

  • IIS/Boncode
  • Apache/mod_cfml
  • Nginx (with some manual headers added)

with as many virtual hosts as you like defined in the web servers. With the flick of a switch in CommandBox, it will create new contexts, each with their own web root, on-demand.

server set modCFML.enable=true

# Set in BonCode or mod_cfml config
server set modCFML.sharedKey=myKey

This new feature does basically what the mod_cfml valve for Tomcat does, but in CommandBox/Undertow. It also works with Lucee Server and Adobe ColdFusion. The only real drawback right now is that on Lucee, CFConfig will import your config into the server context, but since the web-contexts will be created on-the-fly after the server is started, they will not have any config imported into them since they’re created after-the-fact. This only applies to servers with modCFML.enable set to true.

Grab the latest build of CommandBox and give it a go:
https://downloads.ortussolutions.com/#/ortussolutions/commandbox/5.5.0-alpha/

1 Like

Hi Brad,

Do you have an example of what headers to add in NGINX to get this to work?

I want to give this a whirl to create a dev server.

Thanks,

Randy

Hi @Randy_Johnson ! You should just need these:

  • X-ModCFML-SharedKey - Needs to match the ModCFML.sharedKey in server.json
  • X-Tomcat-DocRoot - Needs to contain the web root for the current virtual host

If you do a --debug or --trace server start, there will be lot of info in the console log to help you debug.

Thank You, @bdw429s. I will give this a whirl and report back.

1 Like

Hi @bdw429s,
This worked out good, just had to add 2 headers as you suggested:

proxy_set_header X-ModCFML-SharedKey ____________;
proxy_set_header X-Tomcat-DocRoot /var/www/_______;

Am I able to still use cfconfig to give each virtual host their own datasources and other settings?

Great question. Right now the answer for Adobe is yes only because there’s only a single context!! The answer for Lucee is… no :confused: CFConfig will only apply to the main server context,. which the web contexts inherit from.

There is basically a pretty large decoupling between the CFML bits of CommandBox which power the CLI, announce the server start interception points, and load the config preemptively into the folders where the server is about to start in and the Java-based Runwar tool that actually powers the server once it’s running. When CommandBox starts a server, it fires off a new Java process with a bunch of JVM args that control the server, and then the CLI bows out of the picture and can be shut down, heck even uninstalled at that point (see our finalized Docker images for an example where the server can be still running with CommandBox and it’s CFConfig module fully uninstalled).

The trick is that

  • CommandBox has no idea what contexts will be created ahead of time (and if you had to tell it, it would largely defeat the purpose of mod_cfml)
  • All new contexts are added at run-time minutes, hours, maybe days after the server has started.

Now, this doesn’t mean it isn’t possible if we’re willing to make some assumptions and invent some new conventions-- I just haven’t worked on it yet. What I’d need to do is provide some “hook” inside runwar that can be used to execute something arbitrary any time a new context deploys (which is still tricky since Lucee still has control over WHERE the new contexts will go and Runwar can’t always detect that. I solve this in a non-mod_cfml mode by simply forcing Lucee’s web context location so I know ahead of time, but that doesn’t work as well when there can be an unlimited number of them) So anyway, if I can build a hook into Runwar that fires off some CommandBox command when a new context deploys (assuming CommandBox is available, etc, etc) then I can probably create some convention such as looking for a CFConfig file in the web root and importing it on-the-fly. I’ve put some thought into it, I just haven’t had a chance to try it and I’m not entirely sure how well it will work, lol :slight_smile:

I’ve added this ticket so it doesn’t get forgotten about and we can collect our ideas:
https://ortussolutions.atlassian.net/browse/COMMANDBOX-1445

@Randy_Johnson I wanted to let you know I added some features to CFConfig today to help with this. With the initial release of ModCFML support, CFConfig simply ignored all web-context settings. Now, CFConfig has better support for more than one web context.

Lucee uses a MD5 hash of the web root path as the unique context ID, which is what you see on the file system inside a CommandBox server home with ModCFML enabled

  • WEB-INF/lucee-web-16fde39b2713a9b19596de2f984f75bc
  • WEB-INF/lucee-web-c129de1b57651014ece5df8152b79961
  • etc

CFConfig doesn’t know what web contexts may be created in the future, and Lucee doesn’t even store them anywhere, but CFConfig does know your CommandBox default web root and it can guess where the web contexts will be if you tell it the web roots that they will point to. All web context based settings are now obeyed again for a server with ModCFML switched on, and any web settings will be loaded into the web context corresponding with the default web root of the CommandBox server.

  • cfconfig_web_xxx env vars
  • server.json keys named cfconfig.web pointing to a JSON file path
  • .cfconfig-web.json files found by convention

Furthermore any CLI commands using a fromFormat or toFormat of luceeWeb will point to the web context for the default web root.

In addition, if you have no JSON files, the behavior that auto-imports all old settings when you start a new version of Lucee for the first time, will copy over ALL web context folders that exists in WEB-INF from the old server home to the new server home so long as you are using the default webConfigDir setting.

And finally, you can now specify a JSON file for EACH web context, keyed off the web root path Lucee will see. This can be done via the CLI by specifying a hyphen delimited absolute directory path on the end of your toFormat or fromFormat. Ex:

cfconfig export fromFormat=luceeWeb-/path/to/webroot/site1 to=site1-web-settings.json

The same convention may be used in the server.json where in addition to having a cfconfig.web key, you can also have cfconfig[ "web-/path/to/webroot/site1" ] key(s) like so:

{
    "cfconfig":{
       "server" : ".cfconfig-server.json",
        "web-/path/to/site1":".cfconfig-web-site1.json",
        "web-/path/to/site2":".cfconfig-web-site2.json",
        "web-/path/to/site3":".cfconfig-web-site3.json"
    }
}

When the server starts, CFConfig will pre-emptively create web context folders based on the hash of the web roots under the server’s WEB-INF which will get picked up the first time a web context is accessed and Lucee starts using it.

The cfconfig_web_foo env vars, .cfconfig-web.json file conventions do not currently have any mechanism to point to any web context other than the default one associated with CommandBox’s default web root. This is mostly due to limitations to the valid characters in an env var name and file name which would make it impossible to incorporate a web root path.

It is also still not possible to have default web context settings for new Lucee web contexts that are not known at the time the server starts.

1 Like

Hi Brad,

Wow! This is good stuff. Is this available in the bleeding edge for me to give it a go?

-Randy

@Randy_Johnson These features are part of CFConfig itself which I’ve already released. So just update your CFConfig version to the latest and greatest and you can test it. Remember to test with the --verbose flag and look at the CFConfig portion of the initial job output which will tell you exactly what it is doing and why.