Blog

Brad Wood

December 13, 2016

Spread the word


Share your thoughts

More and more people are starting to use CommandBox for their local development, especially among teams who want to quickly and easily start up the same environment on each of their machines.  That has led to the most common question now for CommandBox users which is:

How do I automatically configure my ColdFusion/Lucee settings on my server?

This is a fair question, and for the most part I've treated configuring the settings in your CF engine to be outside the realm of what CommandBox tries to solve.  However the reality is, the CF engines often times fall short and people need a better way.  Here's a guide for your current options when it comes to configuring the settings on your CF engine.  These are listed in no particular order.

 

Update: This post is pretty old and much of the information here is superseded by a new project called CFConfig.  Please check it out here:

https://cfconfig.ortusbooks.com/introduction/getting-started-guide

The Manual way

Each CommandBox server is a "full" CF server with access to the web-based administrator to add mappings, datasources, mail servers, and any other setting you want.  Right click on the tray icon for your server and choose the option to open the server admin.  For Lucee engines, you'll have an option to open the web admin as well.  Of course, using the web interface is a manual process and not something you can easily deploy to your entire team of developers without them each needing to take those manual steps.  

Application.cfc

This is my favorite and recommended approach.  It's automatic, keeps your configuration with your codebase, and requires no manual process.  The biggest issue with configuring your app server's settings in Application.cfc is that Adobe ColdFusion doesn't provide nearly the same amount of configuration as Lucee, and older versions of Adobe CF don't allow any at all.  Lucee isn't 100% either.  For instance, mail servers and cache connections just got added there in recent releases.  Here's a quick run down:

  • Adobe CF 9 - CF mappings only
  • Adobe CF 10 - CF mappings only
  • Adobe CF 11 - Adds support for data sources (link)
  • Adobe CF 2016 - A few small additions 
  • Lucee 4.x - Many non-compilation server settings (See setting export page in admin)
  • Lucee 5.x - Most non-compilation server settings (See setting export page in admin)

So unless you're on Lucee 5, you're going to be limited.  I'm not aware of a comprehensive overview of Adobe settings available other than this, but here is a Google doc that shows an overview of all the possible Lucee 5 configurations.  Check the Application.cfc column.  

In the Lucee admin, you can click the little question mark under any setting and it will show you what to copy paste into your Application.cfc to set the equivalent setting in your code. There's also an option to export all your Lucee config at once.

For an example of an Application-specific datasource in Adobe CF11+, click here.

Environment variables/Java properties

This is a Lucee 5-only option, not supported on Adobe CF or Lucee 4.x servers at all.  A select number of Lucee settings can be specified as environment variables or Java system properties prior to starting the server.  These are ideal for compilation settings which can't be specified in code.  Here is a Google doc that shows an overview of all the possible Lucee configurations.  Check the EnvVar/SysProp column.  Here are a few big ones:

  • lucee.full.null.support (boolean)
  • lucee.web.dir (path)
  • lucee.base.dir (path)
  • lucee.enable.dialect (boolean)

To use these on a CommandBox server, you can set them as environment variables in your operating system, or package them as Java system properties in your server's server.json like so:

{
  "jvm":{
    "args":"-Dlucee.enable.dialect=true"
  }
}

Basically, prefix the property name with "-D".  This is the standard Java way to set system properties via JVM args.  When the server starts, those Java system properties will be defined and picked up by the engine.

Create a custom CF engine

This is probably the most work, but allows you to customize every nook and cranny of your CF engine.  You can save your own custom WAR file and use it to start your servers.  When you use the cfengine parameter to the server start command, you're probably used to pointing it to the ForgeBox slugs maintained by Ortus.  The cfengine parameter can be any valid CommandBox endpoint ID though including a local file/folder, Git repo, HTTP(s) URL, or custom ForgeBox entry.  So let's say you create a custom ColdFusion 11 WAR that comes pre-loaded with all the settings your app needs and you place it on a shared network drive or web site for your fellow developers.  Just put this in the server.json:

{
  "cfengine" : "/local/path/to/engine.zip"
  or...
  "cfengine" : "http://www.mysite.com/engine.zip"
}

As documented here, the package zip file needs to contain the following two things:

  1. box.json
  2. Engine.[zip|war] (file name doesn't matter)

The easiest way to do this is to start your server with one of our Ortus default engines, log into the administrator and make all your changes, and stop the server and navigate to the server's home directory by running this:

CommandBox> server info property=serverHomeDirectory | open

Zip up the contents of the folder that opens and optionally rename the zip file to have a .WAR extension.  The WEB-INF folder should be in the root of your zip file.  Then package up that new archive in a new zip long with a box.json that minimally has a version, type (cf-engines), and slug.

Copy Configs on first start

This is probably the best one as it is very flexible and will work on any CF engine regardless of vendor or version.  Please note, this requires you to have at least CommandBox 3.4.1-snapshot installed, which is in pre-release at the time of this blog post.  You can grab it here.  In this version of CommandBox, all CF engines have been standardized to expand their WARs to the same consistent directory structure.  We've also enhanced the onServerInstall package script to have access to the server home folder like we did above through the server info command.  onServerInstall will only fire the first time a server is started and the WAR gets installed. You'll need to stopserver forget and then start again for the event to fire again.  If you want to overwrite the configs every time, use the onServerStart event.  

Basically, we'll just copy the XML config files for the server after we've installed the WAR, but before the server actually boots up.  The only drawbacks of this are that the config files differ per engine and per engine version.  If you're starting several different CF engines/versions in the same web root, you'll have some issues with the package script approach since it doesn't have access to the server name being started.

  • For Adobe CF WARs, the xml config files are located in the WAR here: /WEB-INF/cfusion/lib/neo.*.xml
  • For the Lucee server context, the xml config file is located in the WAR here: /WEB-INF/lucee-server/context/lucee-server.xml
  • For the Lucee web context, the xml config file is located in the WAR here: /WEB-INF/lucee-web/lucee-web.xml.cfm

An Adobe CF box.json might look like so.  This will copy my datasource XML file from my web root into the WAR the first time I start up the site.

{
  "name":"My app",
  "version":"1.0.0",
  ...
  "scripts":{
    onServerInstall: "cp neo-datasource.xml '`server info property=serverHomeDirectory`/WEB-INF/cfusion/lib/neo-datasource.xml'"
  }
}

A Lucee Server box.json might look like so.

{
  "name":"My app",
  "version":"1.0.0",
  ...
  "scripts":{
    onServerInstall: "cp lucee-server.xml '`server info property=serverHomeDirectory`/WEB-INF/lucee-server/context/lucee-server.xml'"
  }
}

Pay attention to your quotes. My JSON uses double quotes, and the second parameter to the cp command is wrapped in single quotes, and contains a CommandBox expression wrapped in back ticks.  It's also worth noting the server-related package scripts run with their current working directory set to the web root of the server, so any relative paths will be relative to the web root.  The easiest way to get the config files is to make your desired changes via the web-based admin, then stop the server, open the server home, and copy the file.

I would recommend keeping config files outside the web root so you don't deploy them on accident.  In that case you'd reference them with something like "../config.xml".  Read more about package scripts here.

Conclusion

Hopefully this guide has given you some ideas on how to better package up your servers.  If you want to learn more about server.json in general, check out our docs here.  Please use these examples a starting point and remember you can get even more funky by creating a CommandBox module that listens to the onServerInstall or onServerStart interception points.  They will have access to much more data than the package scripts do.  

 

Add Your Comment

(5)

May 18, 2017 12:11:13 UTC

by Charlie Arehart

Folks reading this post will be interested to learn of the incredible cfconfig cli project, which came out a couple months after this post: https://www.forgebox.io/view/commandbox-cfconfig I suspect it grew out of addressing the challenges above. :-) See the blog post announcing it, for an even more compelling introduction to its awesomeness: https://www.ortussolutions.com/blog/introducing-cfconfig-a-new-way-to-manage-your-cf-servers-configuration-from-the-command-line As an aside, did you guys realize that if we mistype the captcha below, or fail to add the protocol prefix for our URL (like http://), then when the page is re-displayed showing us the error of our ways, it forgets our selection of the "notify me" option? At least it's happening today as I write, on Firefox 53. Thankfully all else is preserved, but some may not notice this is lost and so they may never get emailed about follow-up comments. :-( If you may fix that, you can delete this portion of my comment.

May 18, 2017 15:17:51 UTC

by Brad Wood

Thanks for linking that here Charlie. You are correct that the CLI project grew out of a need to make everything in this blog post even easier. I'll put in a ContentBox ticket to remember the user's select on the "notify me" checkbox when the captcha validation fails. Thanks for mentioning it.

May 18, 2017 15:29:11 UTC

by Charlie Arehart

Thanks, Brad. As for your last point, I thought about making mention of how I supposed I could open a ticket there. I just didn't know what version of ContentBox you'd be using, if that may be useful to know in opening the ticket. I was torn, so opted to mention it here instead and trust you to take that ball and run with it. :-)

Nov 12, 2018 12:47:40 UTC

by Evan Lesmez

Hey! I am running a cf11 server with commandbox and need to add a datasource however we have environmental differences we have to account for in production so it does not work so well to put a path in the Application.cfc. I was trying to access the cfadmin but it requires a password but I do not see where that is provided. Do you have a default password for all server admins?

Nov 13, 2018 12:53:24 UTC

by Brad Wood

Hi Evan Lesmez, this is an older post and much of it is now superseded by our CFConfig project. I would recommend you check it out here: https://cfconfig.ortusbooks.com/introduction/getting-started-guide I have also added a note to the top of this post with the same information. Now, to address your points: -- The default admin password on Adobe servers is "commandbox". This is documented here: https://commandbox.ortusbooks.com/embedded-server/multi-engine-support#coldfusion-admin-settings -- Regarding Application.cfc, you can still make this dynamic either by using env vars, system properties, or just plan if statements in the code that inspect the host name. The same thing applies to CFConfig, where env var and system prop placeholders are supported out of the box in your JSON files.

Recent Entries

Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

As we approach a stable release of BoxLang and our continued marketing reaches more folks, many have asked about its purpose. Why create a new language when the JVM ecosystem already includes established languages like Kotlin, Groovy, and Scala, to name a few.

Luis Majano
Luis Majano
December 18, 2024
ColdBox Free Tip 6 - Using Routing with Wildcard Domains!

ColdBox Free Tip 6 - Using Routing with Wildcard Domains!

ColdBox gives you the flexibility to create domain-specific routes, making it perfect for multi-tenant applications or projects that need to respond differently based on the domain or subdomain being accessed. In this tip, we’ll dive into how to use the withDomain() method to create routes that match specific domains or sub-domains.

Maria Jose Herrera
Maria Jose Herrera
December 18, 2024