Search

Setting up Commandbox/Lucee on Windows behind an IIS proxy

If you haven't managed to get into Commandbox by now, I really feel for you; you've really been missing out for years now. It makes life so much easier in so many ways. I'll spare you the long list of reasons... you're not here for that.

Most of my experience with Commandbox has been on OS X/macOS and Linux (primarily Ubuntu Server). But, at work, where everything ColdFusion related is extremely outdated and Operating Systems all come from the all mighty, omnipotent Microsoft o_O, I haven't had much opportunity to use Commandbox. I am currently reviewing options for an upgrade to CFML engines created in this decade and am finally looking at using Commandbox to simplify things (setting up new dev/qa/staging/prod servers, managing upgrades to engines, settings, modules and fusion-reactor, etc...). That, unfortunately, does not include switching servers or dev machines to Linux so I need to do all of this for Windows & IIS.

I'll be running Lucee through Commandbox and then using IIS as a proxy to those Lucee instances. I'll start the good stuff assuming you already have a Windows Server (2016 or up) ready and waiting to install IIS.

I will be doing this a lot so I've scripted the majority of the work. I will break the script down below.

This script assumes C:\inetpub\mysite already exists. If It does not, or you want your application to live elsewhere, change the $websitename and $webroot values accordingly and make sure the directory exists.


[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;

$boncodeurl="https://github.com/Bilal-S/iis2tomcat/releases/download/1.0.41/AJP13_v1041.zip"
$commandboxurl="https://www.ortussolutions.com/parent/download/commandbox/type/windows-jre64"
$commandboxpath='C:\CommandBox'
$tempdir="C:\Windows\Temp"
$websitename=mysite
$webroot="C:\inetpub\$($websitename)"

Install-WindowsFeature Web-Server -IncludeManagementTools
Install-WindowsFeature Web-Http-Redirect
Install-WindowsFeature Web-Custom-Logging
Install-WindowsFeature Web-Request-Monitor
Install-WindowsFeature Web-Http-Tracing
Install-WindowsFeature Web-Filtering
Install-WindowsFeature Web-Basic-Auth
Install-WindowsFeature Web-IP-Security
Install-WindowsFeature Web-Windows-Auth
Install-WindowsFeature Web-Net-Ext45
Install-WindowsFeature Web-AppInit
Install-WindowsFeature Web-CGI
Install-WindowsFeature Web-ISAPI-Ext
Install-WindowsFeature Web-ISAPI-Filter
Install-WindowsFeature Web-Includes
Install-WindowsFeature Web-Scripting-Tools
Install-WindowsFeature Web-Mgmt-Service


if (-not (Test-Path -LiteralPath $commandboxpath -PathType Container)) {
(New-Object System.Net.WebClient).DownloadFile($commandboxurl, "$($tempdir)\commandbox.zip")
(New-Object System.Net.WebClient).DownloadFile($boncodeurl, "$($tempdir)\boncode.zip")

mkdir $commandboxpath

Add-Content "$($commandboxpath)\commandbox.properties" $("commandbox_home=$(ConvertTo-Json $commandboxpath)" -replace '"', '')

Expand-Archive -LiteralPath "$($tempdir)\commandbox.zip" -DestinationPath $commandboxpath
Expand-Archive -LiteralPath "$($tempdir)\boncode.zip" -DestinationPath $($tempdir)

Start-Process cmd -Argument "/c $($commandboxpath)\box" -WorkingDirectory $commandboxpath

Write-host "===================================================================================================="
Write-host "Continue once commandbox is done configuring itself and you see the super cool Commandbox ASCII art "
Write-host "===================================================================================================="
pause


Stop-WebSite -Name "Default Web Site"

New-WebAppPool $websitename

New-WebSite -Name $websitename -ApplicationPool $websitename -Port 80 -Hostheader "" -PhysicalPath $webroot

start-process cmd -Argument "/c C:\commandbox\box server start name=$websitename host=127.0.0.1 cfengine=lucee webroot=$($webroot) serverconfigfile=$($webroot)\server.json openbrowser=false"
}


First, note that this is a one time script that needs some manual handholding. I only put it together to save time on a repetitive task I would be performing.

So, what is it doing?

First, it is installing IIS and a number of IIS features.

Next, it checks to see if C:\Commandobox exists. If it does, it assumes it has already be ran and will stop there. Otherwise, it will download the commandbox.xip file and boncode.zip files from the appropriate places.

Next, the script will create the C:\Commandbox directory and add a commandbox.properties file to that directory. The file will just contain one line


commandbox_home=C:\\Commandbox


This properties file will ensure that, no matter where box.exe is executed from, it uses C:\Commandbox as its home path. If we didn't hav this, and you didn't specify it every time the box command was executed, Commandbox would set itself up in the current users home directory. That is not ideal for an actual server.

Once the commandbox.properties file is in place, the script will extract commandbox.zip to C:\commandbox and boncode.zip to C:\windows\temp\ (which will result in the boncode installation files living in C:\windows\temp\AJP13).

Next, the script will open a new CMD window and execute the first box command. The first time CommandBox runs, it will set itself up and it may take a minute. The Powershell script behind the new command prompt window will pause. Do not return to the Powershell window and continue the script until Commandbox has finished configuring itself, shows you the welcome screen and gives you a "CommandBox>" prompt.

Once you have the "CommandBox>" prompt, return to the Powershell window and press any key to continue. Once you do, the script will stop the default IIS website, create a new application pool with the name specified in $websitename and create a new website with the same name. The new site will use the new app pool and point to the $webroot path. It will also have a wildcard hostheader on port 80.

Finally, the script will start a new CommandBox server that points to the same $webroot, setup the latest version of Lucee on the local host (127.0.0.1). You can return to the CommandBox cmd prompt and run a "server list" command to see the server details.

The output will look something like this.


mysite (running)
http://127.0.0.1:51309
CF Engine: lucee 5.3.5+92
Webroot: C:\inetpub\mysite\
Last Started: 04-Apr-2020 05:47:31


Now, if you run the command "server open", it will open the default browser and take you to the new site. (i.e. http://127.0.0.1:51309). If you append /lucee/admin/server.cfm to that URL, you should see the Lucee admin screen. The screen will likely explain that no password has been set and tell you that you should create a password.txt file in the appropriate place then click the import button. You could, of course do exactly that (the location it is referring to would be something similar to C:\CommandBox\server\7C8D64C733E28620EE1D68398BEB1AE1-mysite\lucee-5.3.5.92\WEB-INF\lucee-server\context). A better way of managing your servers configuration would be to use the cfconfig. And, now that commandbox is installed, it is ridiculously easy to install and use cfconfig.

Back in the Commandbox window, run the command "install commandbox-cfconfig". After a few seconds, cfconfig will be installed. Once it is, you can run the following command to set the Lucee admin passwords.


cfconfig set adminPassword=MySecretPassword


That's all there is to it. Now, when you navigate to the Lucee server or web admin contexts, you can enter your new password to login.

You'll want to read more about cfconfig; between it and Application.cfc, I never log into the server admin UI anymore.

Ok. Enough about that. To finalize the IIS proxy for your new Commandbox server, open up C:\windows\temp\ajp13 and run the Connector_Setup.exe installer. It will ask you a number of questions, to most of which, you should respond with your best judgement but most defaults are perfectly fine for the first instance (you'll want to, at least, change the port, if you run multiple sites later).

Apache Tomcat Server: localhost
Apache Tomcat port: 8009
Enable Remote Access to Apache Tomcat: I always disable this
Enable x-forwarded-for translation: Yes (otherwise, you might see 127.0.0.1 in cgi.remote_addr)
The next screen will ask which IIS sites to enable, Select "Let me choose" and only select your new IIS website.
Handler Mapping: You will want to, at least, make sure CFC and CFM is selected here. It is the only option I use.
Environment Configuration: I select both boxes. There is a good description of both options on the screen.
Install.

The boncode installer is easily scripted and you can find those details at boncode.net. If you drop a installer.settings file in the same directory as the exe and then run the exe form a command prompt (not the commandbox command prompt), it can do everything for you. However, it seems to me that the scripted install is slower for some reason. If I were setting this up to run on a bunch of servers while I walked away, I would use the scripted method. The following installer.settings file content should get you everything you got with the manual isntallation.


[Setup]
installType=global
acceptLicense=1
enableRemote=0

[Handlers]
installCF=1
installJSP=0
installWildCard=0

[Tomcat]
server=localhost
ajpPort=8009
configureServerXml=0

[Settings]
allowEmptyHeaders=1
enableRemoteIpDetection=1

[Sites]
mysite=1


Once the AJP connection is done installing, you can restart the commandbox server and you should be all set. To restart the commandbox server, simply run the "restart" command in the commandbox cmd window.

You should take a second to realize what the AJP connector did to your application so you aware and do not inadvertently break anything. First, it created a web.config (or updated your existing web.config) to add the handler mappings for CFM and CFC. Next, it created a /BIN directory in the webroot that contains a couple of .dll files and settings file. You may also find a .txt file but it isn't important.

You should now be able to open a browser and navigate to http://myServerNameOrIp and see your new site. All CFM and CFC requests will be passed on to the underlying Jboss server (and to Lucee) while IIS handles all the static content files (css, js, images, etc...).

Update: 5/22/2020
If you are noticing a significant increase in latency when going through IIS/Boncode vs directly to Undertow, check out this issue.
https://github.com/Bilal-S/iis2tomcat/issues/95

Most Recent Photos