Migration - Upgrades

How to Automate ColdFusion Deployment During Migration

A thoughtful, repeatable Deployment process is the difference between a smooth ColdFusion Migration and a week of firefighting. Upgrading to a newer ColdFusion engine (e.g., Adobe ColdFusion 2021/2023 or Lucee), modernizing the runtime (JDK updates, containers), and converging to CI/CD and Infrastructure as Code reduces risk, boosts Performance, and enables rollbacks and zero-downtime releases.

## Prerequisites / Before You Start

– Backups and snapshots
– Full system image or VM snapshot of the existing server(s).
– ColdFusion Configuration: export ColdFusion Administrator settings; keep copies of neo-*.xml as a fallback (e.g., neo-datasource.xml, neo-cron.xml, neo-mail.xml).
– Application code and assets (including CFML, Custom tags, components, images, static files).
– Database backups and a verified restore process.
– Web server configs (IIS site export, Apache/Nginx virtual host files).
– SSL/TLS certificates and private keys.

– Version inventory and compatibility
– Current ColdFusion engine and update level (Adobe ColdFusion 11/2016/2018/2021/2023 or Lucee 5.x).
– Java/JDK version in use and target (collect heap settings, GC settings).
– Libraries and extensions: JDBC drivers, PDFg, Solr, Image/Charting, cfdocument/cfpdf usage.
– Web server connector type/version (IIS connector via wsconfig or Apache mod_jk/mod_proxy_ajp).
– OS details (Windows, RHEL/CentOS, Ubuntu) and bitness (64-bit).
– Legacy Features to review: Remote Admin APIs, BlazeDS, Flex remoting, Verity (obsolete), old ORM behavior.

– Tooling and Automation stack (choose what fits your environment)
– Source control: Git repository with application code and Configuration artifacts.
– CI/CD: GitHub Actions, Jenkins, GitLab CI, Azure DevOps, or CircleCI.
– ColdFusion Automation helpers:
CommandBox for local dev, server orchestration, cfengine selection.
– CFConfig to export/import CFAdmin settings as code.
– Adobe CF Package Manager (cfpm) for installing/removing modules.
– Adobe Lockdown Tool for Security baselining (if using Adobe CF).
Infrastructure as Code and config management:
– Docker and container registry, or VM images via Packer.
– Kubernetes/OpenShift or AWS ECS/Fargate for orchestration (optional).
– Ansible/Chef/Puppet for OS-level automation if not containerizing.
– Terraform for cloud resources and network/load balancer configuration.
– Observability and QA:
– Log aggregator (ELK/Opensearch, Splunk).
– Metrics/APM (New Relic, AppDynamics, Prometheus).
– Synthetic checks and load testing tools (k6, JMeter).

– Access and secrets
– Credentials for staging/prod databases, mail servers, Cloud services (S3, Azure Storage).
– Secret store chosen: Vault, AWS Secrets Manager, Azure Key Vault, or Kubernetes Secrets.
– Non-interactive access for CI/CD agents to deploy targets.

– Acceptance tests and rollback plan
– Smoke tests and regression suites covering critical flows.
– Clear rollback approach (image or container tag, DB rollback strategy).

## Migration strategy Overview

### Select a release strategy

– Blue-green deployments
– Two production-like environments (Blue and Green). Only one is live. Deploy to the idle one, test, then switch traffic via the load balancer. Fast rollback by flipping back.
– Canary releases
– Route a small percentage of traffic to the new stack, monitor, then ramp up. Useful for high-traffic sites.
– In-place upgrade
– Higher risk and usually not recommended. Consider only for simple environments or internal systems with generous Maintenance windows.

### Recommended tooling mix

– Runtime: containerized ColdFusion (Adobe CF 2023 or Lucee 5.x/6) or immutable VM images.
– Configuration: CFConfig for CFAdmin, cfpm for modules, Ansible for OS packages.
– CI/CD: pipeline that builds artifact, provisions environment, and deploys with automated tests.
Security: Adobe Lockdown Tool or hardened base images; AJP secrets; minimal surface area via cfpm.

## Step-by-Step Migration and Automation Guide

### 1) Inventory and export configuration

1. Catalog current settings
– Note datasources, mail server, Scheduled tasks, caching, session/storage, JVM memory, and custom libraries.
– Export current ColdFusion Administrator settings. Prefer automation-first:
– If using CommandBox-managed servers, export with CFConfig:
– box install commandbox-cfconfig
– cfconfig export to=cfconfig.json
– If exporting from a standalone Adobe CF installation, you can point CFConfig at the installation path (consult CFConfig docs for engine and path flags). Keep a copy of the generated cfconfig.json in source control (without secrets) or in your secret store.
– Back up neo-*.xml files as a last resort snapshot.

See also  How to Ensure SEO Continuity After Migration

2. Extract secrets safely
– Replace passwords (datasources, mail) in cfconfig.json with environment variable tokens (e.g., ${DSN_APP_PWD}).

3. Document web connectors
– For IIS, record site IDs and bindings; for Apache/Nginx, capture vhost files. Plan to automate connector creation (wsconfig) or Reverse proxy Integration.

4. Verify Java/JDK
– Document existing JVM version and args (Xms/Xmx, GC) and map them to the target engine.

### 2) Create a reproducible runtime

Choose containers or immutable VMs. Containers are simpler to automate and test.

– Example: CommandBox-based container for Adobe CF or Lucee (flexible cfengine selection)

Dockerfile:

FROM ortussolutions/commandbox:latest
# Choose your engine and version (adobe@2023 or lucee@5)
ENV CFENGINE=adobe@2023
# Auto-accept EULA for Adobe (ensure Licensing Compliance)
ENV EULA=accept
# Copy app code
WORKDIR /app
COPY . /app
# Bring CFConfig file
COPY ./ops/cfconfig.json /app/cfconfig.json
# Server configuration
COPY ./ops/server.json /app/server.json
# Install CLI modules (CFConfig, etc.)
RUN box install commandbox-cfconfig
# Import CFAdmin settings at startup
ENV CFCONFIG=/app/cfconfig.json
# Expose web port
EXPOSE 8080

server.json example:

{
“app”: {
“cfengine”: “adobe@2023”
},
“web”: {
“host”: “0.0.0.0”,
“http”: { “port”: 8080 }
},
“JVM”: {
“heapSize”: “1024”,
“args”: “-Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom”
},
“CFConfig”: {
“autoImport”: true
},
“env”: {
“CF_ADMINPASSWORD”: “${CF_ADMIN_PWD}”
}
}

Notes:
– CommandBox starts Tomcat under the hood and integrates CFConfig automatically.
– For Adobe CF’s built-in package manager, you can run cfpm in an init script to install only necessary modules.

– Example: Adobe CF with cfpm in a container entrypoint

# In an entrypoint script
cfpm list available
cfpm install

Tip: Run cfpm list to discover exact package names in your target version.

– IIS/Windows scenario (non-container)
– Use PowerShell DSC or Ansible win_* modules to install ColdFusion, JDK, apply CF updates, and run wsconfig silently.
– Use CFConfig CLI on the server to import cfconfig.json.
– Use Adobe Lockdown Tool in unattended mode.

### 3) Automate database migrations and secrets

– Migrations
– Use Liquibase or Flyway to version schema changes:

# GitHub Actions step example
– name: Run Flyway migrations
uses: flyway/flyway-action@v2
with:
url: ${{ secrets.DB_URL }}
user: ${{ secrets.DB_USER }}
password: ${{ secrets.DB_PASSWORD }}
locations: filesystem:db/migrations

– Secrets
– Never hardcode passwords in cfconfig.json or Dockerfiles. Use environment variables mapped from a secret manager:
– Kubernetes: reference secrets as env vars.
– GitHub Actions: use repository secrets to inject during deploy.
– Vault/Key Vault/Parameter Store: fetch at runtime via sidecar or init script.

### 4) Build the CI pipeline

– Build
– Lint CFML (cflint) and run unit tests (TestBox) if available.
– Build a Docker image and push to a registry.

– Example: GitHub Actions workflow

name: build-and-deploy
on:
push:
branches: [ “main” ]
jobs:
build:
runs-on: ubuntu-latest
steps:
– uses: actions/checkout@v4
– name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: ’17’
distribution: ‘temurin’
– name: Build container
run: |
docker build -t ghcr.io/org/cf-app:${{ github.sha }} .
echo $CR_PAT | docker login ghcr.io -u $GITHUB_ACTOR –password-stdin
docker push ghcr.io/org/cf-app:${{ github.sha }}
deploy-staging:
needs: build
runs-on: ubuntu-latest
steps:
– name: Deploy to staging (ECS/K8s)
run: |
# update service or helm release to new image tag
# kubectl set image Deployment/cf-app cf=ghcr.io/org/cf-app:${{ github.sha }}

– Jenkinsfile (groovy) sketch

pipeline {
agent any
stages {
stage(‘Build’) {
steps {
checkout scm
sh ‘docker build -t registry/cf-app:${BUILD_NUMBER} .’
sh ‘docker push registry/cf-app:${BUILD_NUMBER}’
}
}
stage(‘Migrate DB’) {
steps {
sh ‘flyway -url=$DB_URL -user=$DB_USER -password=$DB_PASSWORD migrate’
}
}
stage(‘Deploy Blue’) {
steps {
sh ‘./ops/deploy-blue.sh registry/cf-app:${BUILD_NUMBER}’
}
}
stage(‘Smoke Tests’) {
steps {
sh ‘./ops/smoke.sh https://blue.example.com/health’
}
}
stage(‘Switch Traffic’) {
steps {
sh ‘./ops/switch-lb.sh blue’
}
}
}
post {
failure {
sh ‘./ops/rollback.sh’
}
}
}

### 5) Configure connectors and routing

– Containers behind Nginx/Apache
– Prefer HTTP or AJP with secrets. Example Nginx Reverse proxy to container: proxy_pass http://cf-app:8080.

– IIS with wsconfig
– Use the Adobe wsconfig tool in silent mode during provisioning to bind the connector to the desired site ID and application pool.
– Keep an idempotent script that can recreate the connector after patching. Consult your ColdFusion version docs for exact flags and ensure AJP secret is set when applicable.

– Load balancer
– Configure sticky sessions if using in-memory sessions. Better: externalize sessions (database or Redis) to allow rolling updates without session loss.

See also  How to Reduce Risk During Large ColdFusion Migrations

### 6) Install and automate ColdFusion modules

– Use cfpm in non-interactive mode to install only what you need (e.g., PDFg, Solr, SAML, S3).
– Reduce attack surface by uninstalling unused modules.

Example install at container start:

if command -v cfpm >/dev/null 2>&1; then
cfpm install pdfg solr s3
fi

Tip: Validate actual module names with cfpm list on your target engine.

### 7) Security hardening as code

– Adobe Lockdown Tool in unattended mode (for Adobe CF). Run as a CI step or as part of image build.
– Ensure secure AJP configuration; set requiredSecret where applicable, restrict to localhost, or prefer HTTP proxy with mTLS behind the LB.
– Force TLS 1.2+ to backend systems. Update mail/SMS integrations to modern ciphers.

### 8) Smoke tests and health checks

– Add a lightweight /health endpoint that checks:
– App startup state and version
Database connectivity (simple SELECT 1)
– Cache/backend services reachability

– Include smoke tests in the pipeline prior to switching traffic.

Example curl script:

curl -fsS https://staging.example.com/health | jq .

### 9) Execute blue-green cutover and rollback

– Deploy the new image to Green, run DB migrations, warm caches, prebuild Solr indexes if used.
– When smoke tests pass, flip the load balancer target from Blue to Green.
– Keep Blue running for a defined period for quick rollback.
– Rollback plan:
– Repoint LB back to Blue.
– Revert DB migrations if breaking (prefer additive, backward-compatible migrations to avoid rollbacks).

### 10) Observability and log shipping

– Standardize logs to JSON and forward to your aggregator.
– Add application version/tag to logs and a /version endpoint.
– Capture JVM metrics and GC logs for Performance triage.

## Risks, Common Issues, and How to Avoid Them

– JVM and CF engine differences
– Risk: Newer JDK or CF version changes default encodings, date/time handling, or memory behavior.
– Avoid: Explicitly set file.encoding=UTF-8; pin JDK version; test with production-like data.

– Connector mismatches
– Risk: Wrong IIS/Apache connector version or misconfigured AJP leading to 500 errors or security gaps.
– Avoid: Automate connector provisioning; secure AJP with a secret or disable it and use HTTP proxy; test under load.

– Session loss during deploys
– Risk: Users lose sessions on instance restart.
– Avoid: Externalize sessions (database, Redis); enable sticky sessions at LB; roll pods incrementally.

– Datasource and driver changes
– Risk: JDBC drivers bundled with the new engine behave differently.
– Avoid: Ship known-good JDBC driver versions; validate isolation levels and connection pool settings; run Integration tests.

Scheduled tasks and cfmail differences
– Risk: Scheduled tasks don’t migrate or run on the wrong node.
– Avoid: Manage tasks via CFConfig or dedicated job scheduler; single-writer lock; ensure mail TLS settings are updated.

cfdocument/cfpdf and imaging
– Risk: Rendering differences, fonts missing, or headless environment issues in containers.
– Avoid: Package fonts in the image; verify wkhtmltopdf/PDFg configurations; test complex documents.

– SOLR/collections
– Risk: Indexes not migrated or incompatible.
– Avoid: Rebuild indexes on deploy; containerize Solr; pin schema versions.

– Security regressions
– Risk: Default admin password, exposed CFIDE, or verbose error pages.
– Avoid: Set CF admin password via env; restrict admin access; run Lockdown Tool; configure secure error templates.

– Time zone and locale
– Risk: Container defaults to UTC surprises code.
– Avoid: Set TZ explicitly and test date/time logic.

## Post-Migration Checklist / Validation Steps

– Platform and runtime
– CF server starts cleanly; no fatal errors in logs.
– Correct engine version and update level (Adobe HF patches applied).
– JVM memory matches expectations; GC logs show healthy behavior.

– ColdFusion Administrator config
– Admin password set and locked down.
– Datasources: Test connections succeed; connection pools stable under load.
– Mail server: Send a test email via cfmail page.
– Caching providers configured (RAM/Redis) and used by the app.
Session management/timeout values correct.
– Scheduled tasks present, enabled, and running on intended nodes only.

See also  How to Fix Broken Links After ColdFusion Migration

– Modules and libraries
– cfpm modules installed as required; remove unused modules.
– Correct JDBC driver versions on classpath.
– Fonts and native libs present for PDF/Image Features.

– Web tier and routing
– IIS/Apache/Nginx routing correct; SSL configured; HSTS as required.
– AJP configuration secured or disabled.
– Gzip/Brotli compression enabled; static assets cached properly.

– Application verification
– Smoke tests pass: login, search, checkout, API endpoints.
Error handling and 404/500 pages render as expected.
– Feature flags and environment toggles set for the right environment.

– Observability
– Logs visible in aggregator; structured with correlation IDs.
– Metrics/APM receiving data; alert thresholds calibrated.
– Dashboards show healthy latencies and error rates.

– Data and background jobs
– DB migrations applied; zero drift detected.
– Solr or search indexes rebuilt and queryable.
– Batch jobs and queues are functioning.

– Security
– Admin endpoints restricted to trusted networks.
– TLS 1.2+ enforced; cipher suites hardened.
– Vulnerability scan shows no criticals; OS packages updated.

– Rollback readiness
– Previous blue environment left intact and documented for quick failback.
– Backup restoration tested.

## Example Automation Artifacts

### Ansible snippet for Linux host provisioning

– hosts: cf_nodes
become: yes
tasks:
– name: Install JDK
apt:
name: temurin-17-jdk
state: present
– name: Deploy ColdFusion container service
copy:
src: docker-compose.yml
dest: /opt/cf/docker-compose.yml
– name: Start service
shell: Docker Compose up -d

### Nginx reverse proxy to ColdFusion container

server {
listen 443 ssl http2;
server_name app.example.com;

location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://cf-app:8080;
}

location /health {
proxy_pass http://cf-app:8080/health;
}
}

### Blue-green switch (pseudo)

# Switch target group weights
aws elbv2 modify-listener –listener-arn $LISTENER \
–default-actions Type=forward,TargetGroupArn=$BLUE,Weight=0,Type=forward,TargetGroupArn=$GREEN,Weight=100

## Quick Compatibility Notes

– Adobe ColdFusion 2023: Java 17 support, modular installation via cfpm, updated security defaults.
– Lucee: Fast startup, lightweight; verify tag/function differences and admin settings via CFConfig.
– CommandBox: Excellent for local dev parity, scripting servers, and CFConfig integration.

## FAQ

#### How do I export and import ColdFusion Administrator settings safely?
Use CFConfig to export to a JSON file and store it in source control minus secrets. Replace sensitive values with environment variable tokens (for example, ${DSN_APP_PWD}). During deploy, your CI/CD injects real values from a secret manager, and CFConfig imports them on server start. Keep a snapshot of neo-*.xml as a fallback but do not rely on manual file copies for automated pipelines.

#### Is Docker mandatory for automating ColdFusion deployments?
No. Containers simplify reproducibility and blue-green strategies, but you can achieve automation with immutable VM images (Packer) and Configuration management (Ansible/DSC). The key is declaring CF settings as code (CFConfig), scripting module installs (cfpm), and using a CI/CD pipeline to build, test, and deploy consistently.

#### Can I run Adobe ColdFusion and Lucee side by side during migration?
Yes. Use separate containers or VMs and route traffic selectively via a load balancer. This is common in canary migrations when porting CFML to Lucee. Validate tag/function differences, ORM behavior, and libraries. Store configuration per-engine and automate both with CFConfig where supported.

#### How do I automate IIS connector setup without downtime?
Script wsconfig in silent mode to create connectors for the “green” site ahead of time, bind it to a non-public host header, and warm it up. After validation, swap bindings or update the load balancer. Keep the script idempotent so you can re-run it after patches. Secure AJP and confirm the app pool identity and permissions.

#### What is the simplest rollback plan if something goes wrong?
Keep the previous version running as “blue,” retain its database compatibility (use backward-compatible schema changes), and switch the load balancer back. For stateful changes, externalize sessions and queues. Tag images by commit hash, so reverting is just repointing to the prior tag and flipping traffic.

About the author

Aaron Longnion

Aaron Longnion

Hey there! I'm Aaron Longnion — an Internet technologist, web software engineer, and ColdFusion expert with more than 24 years of experience. Over the years, I've had the privilege of working with some of the most exciting and fast-growing companies out there, including lynda.com, HomeAway, landsofamerica.com (CoStar Group), and Adobe.com.

I'm a full-stack developer at heart, but what really drives me is designing and building internet architectures that are highly scalable, cost-effective, and fault-tolerant — solutions built to handle rapid growth and stay ahead of the curve.