Exécuter Adobe ColdFusion sur ARM: une aventure en territoire non pris en charge

J'ai essayé de տեղափոխer Adobe ColdFusion vers AWS Graviton. ColdFusion a fonctionné. Le connecteur, non. Puis CommandBox a fait disparaître tout le problème.

AWS Cost Explorer n’arrêtait pas de me relancer. Chaque mois, il me faisait gentiment remarquer que je pouvais économiser une somme respectable en migrant mes instances EC2 de x86 vers AWS Graviton. La recommandation n’avait rien de subtil. Elle était persistante. Selon AWS, mes charges de travail étaient d’excellentes candidates pour ARM.

Sur papier, ça avait tout son sens. ColdFusion fonctionne sur Java. Java fonctionne à merveille sur ARM. Alors... pourquoi pas ColdFusion?

À quel point ça pouvait être difficile?

Cette question a lancé d’innombrables impasses techniques au fil des ans. Celle-ci n’a pas fait exception. Je me suis dit que j’allais passer un après-midi à prouver que ColdFusion fonctionnait, basculer quelques instances vers Graviton, et empocher les économies mensuelles.

À la place, j’ai passé des jours à pourchasser des incompatibilités obscures dans les installateurs, les connecteurs de serveur Web, les binaires natifs, les paquets AJP, les modules Apache, les conteneurs Docker, et bien trop de moments à remettre en question mes choix de vie.

Le plus drôle, c’est que ColdFusion lui-même n’était pas le problème. En fait, une fois les obstacles d’installation franchis, ColdFusion est étonnamment heureux de fonctionner sur ARM. Java, lui, se fiche complètement de l’architecture CPU sur laquelle il s’exécute.

Le vrai problème s’est révélé être tout ce qui entourait ColdFusion.

Cet article documente le parcours, les fausses pistes, les découvertes, et finalement pourquoi quelque chose d’aussi évident n’est toujours pas une architecture de déploiement prise en charge. J’espère que cela évitera au prochain développeur curieux de répéter la même expérience... à moins, bien sûr, que ce genre d’aventure vous plaise.

D’abord, un petit problème d’architecture

Il y avait un important obstacle avant même que je puisse commencer. On ne peut pas simplement convertir une instance EC2 existante de x86 à Graviton. Les processeurs Graviton utilisent l’architecture ARM64, donc il ne s’agissait pas d’arrêter une instance, de changer son type, puis de la redémarrer. Il me fallait une nouvelle instance ARM64.

Pour l’expérience, j’ai lancé une instance AWS Graviton sous Ubuntu 24.04 ARM64. L’environnement de test final ressemblait à ceci:

  • AWS Graviton ARM64
  • Ubuntu 24.04
  • Apache 2.4.58
  • Adobe ColdFusion 2025 Update 11
  • Java 21 ARM64

Mon infrastructure existante utilise Apache en frontal de ColdFusion, Apache communiquant avec ColdFusion par l’intermédiaire du connecteur de serveur Web Adobe et d’AJP. Ce détail deviendra plutôt important plus tard.

Mais d’abord, il fallait que j’installe ColdFusion.

Problème numéro un: le JVM

L’installateur de ColdFusion n’est pas conçu pour ARM64. Ce n’était pas particulièrement surprenant. Adobe ne présente pas Linux ARM64 comme une plateforme ColdFusion prise en charge, alors je savais dès le départ que je m’éloignais de la route balisée.

ColdFusion est aussi fourni avec son propre environnement d’exécution Java. Un environnement Java x86_64. Un exécutable x86_64 n’est pas particulièrement utile sur une machine ARM64.

Heureusement, c’était l’un des problèmes les plus simples à régler. J’ai installé une version ARM64 de Java 21 et remplacé le JVM ColdFusion fourni, en conservant l’original à:

/opt/coldfusion2025/jre-x86_64-original/

Puis quelque chose d’intéressant s’est produit. ColdFusion a démarré. Pas « a à moitié démarré ». Pas « a démarré après émulation de x86 ». ColdFusion fonctionnait réellement nativement sur Java ARM64.

C’était le premier grand résultat de l’expérience. ColdFusion lui-même peut fonctionner sur ARM64.

Ça a du sens quand on pense à ce qu’est fondamentalement ColdFusion. Le moteur CFML s’exécute dans le JVM, et le JVM abstrait la majeure partie de l’architecture du processeur sous-jacent.

À ce stade, je me sentais plutôt satisfait de moi. AWS avait raison. Java avait raison. J’avais raison. Il était temps de brancher Apache et de proclamer victoire.

Le narrateur, probablement avec ce timbre velouté à la Morgan Freeman: il n’a pas proclamé victoire.

Place à wsconfig

Si vous avez administré ColdFusion pendant un certain temps, vous connaissez probablement l’outil de configuration de serveur Web d’Adobe, wsconfig. D’un autre côté, si vous administrez ColdFusion et que vous n’êtes pas familier avec wsconfig, vous devriez l’être.

wsconfig est l’outil de configuration de serveur Web d’Adobe. C’est lui qui relie un serveur Web externe comme Apache ou IIS à ColdFusion, en installant et en configurant le connecteur natif qui transmet les requêtes entre les deux.

Quelques bonnes pratiques méritent d’être retenues:

  • Utilisez wsconfig plutôt que de copier manuellement les fichiers du connecteur un peu partout. Laissez ColdFusion créer et maintenir sa configuration de connecteur lorsque c’est possible.
  • Relancez le connecteur après les principales mises à jour de ColdFusion lorsque Adobe l’exige. Mettre ColdFusion à jour ne veut pas forcément dire que votre connecteur de serveur Web existant est à jour.
  • Sachez vers quelle instance ColdFusion un connecteur pointe. Cela devient particulièrement important sur les serveurs qui exécutent plusieurs instances.
  • Faites une sauvegarde de la configuration de votre serveur Web avant de modifier les connecteurs. wsconfig modifie la configuration d’Apache ou d’IIS, et le retour en arrière est beaucoup plus simple quand on sait exactement ce qui a changé.
  • Ne considérez pas le connecteur comme un morceau de plomberie invisible. Sachez où se trouvent sa configuration et ses journaux. Quand les requêtes atteignent Apache ou IIS mais n’atteignent mystérieusement pas ColdFusion, le connecteur est l’un des premiers endroits à vérifier.

Pour la plupart des installations ColdFusion, vous lancez wsconfig, il fait son travail, et vous n’y pensez plus que rarement. Malheureusement, j’étais sur le point de le connaître très bien.

Je l’ai lancé. Il a généré la configuration Apache attendue. Et Apache a aussitôt refusé de charger le connecteur.

La raison est devenue évidente dès que j'ai inspecté mod_jk.so. Adobe fournit avec ColdFusion un connecteur de serveur Web compilé. Ce binaire a été compilé pour x86_64. Apache était en ARM64. On ne peut pas charger un module Apache x86_64 dans un processus Apache ARM64 pas plus qu'on ne peut mettre une transmission de Volkswagen dans un grille-pain.

C'est à ce moment-là que l'expérience a changé. Ce n'était pas ColdFusion qui m'empêchait de rouler sur ARM. C'était le connecteur de serveur Web de ColdFusion d'Adobe.

Bon. Je vais le construire moi-même.

Le connecteur d'Adobe est basé sur mod_jk d'Apache Tomcat. Et mod_jk est open source. Problème réglé, non?

J'ai installé les outils de développement nécessaires, y compris apache2-dev et build-essential, téléchargé le code source d'Apache Tomcat Connectors, puis compilé mod_jk 1.2.50 directement sur la machine ARM.

J'ai obtenu exactement ce que je voulais - un mod_jk.so ARM64 natif.

Apache pouvait le charger. Pendant quelques minutes splendides, on aurait dit que toute cette entreprise ridicule allait fonctionner. Puis j'ai essayé de l'utiliser pour vrai.

Le mod_jk d'Adobe n'est pas tout à fait mod_jk

Le premier problème était la configuration. La configuration générée par wsconfig d'Adobe contenait des directives et des propriétés de worker que le mod_jk Apache standard ne reconnaissait pas.

Parmi elles, il y avait JkWorkersFileReload et des propriétés comprenant :

  • heartbeat_interval
  • heartbeat_limit
  • worker.cfusion.heartbeat_servlet_path
  • worker.cfusion.monitoringsecret

Ces éléments ne font pas partie du connecteur standard que je venais de compiler. J'ai donc commencé à enlever les éléments spécifiques à Adobe. À la fin, j'ai réduit la configuration à l'essentiel nécessaire pour établir un worker AJP, y compris le port AJP de ColdFusion et le secret.

Apache a démarré. mod_jk a été chargé. Le worker s'est connecté à ColdFusion. On avançait enfin. Il était temps de crier victoire.

Le narrateur, probablement dans ce timbre doux à la Morgan Freeman : il n'a pas crié victoire.

Les requêtes ne fonctionnaient toujours pas.

Unknown AJP protocol code: 0F

Les journaux d'Apache ont commencé à signaler quelque chose que je n'avais jamais vu auparavant : Unknown AJP protocol code: 0F. C'était considérablement plus intéressant qu'une erreur de configuration.

Apache se connectait à ColdFusion. ColdFusion répondait. Mais la réponse contenait un message AJP que le connecteur Tomcat standard ne comprenait pas.

Au début, il y avait plein de choses raisonnables à soupçonner. Peut-être avais-je une incompatibilité de configuration AJP. Peut-être que c'était lié aux attributs de requête. Peut-être que la configuration du secret était erronée. Peut-être qu'Adobe s'attendait à une poignée de main subtilement différente.

J'ai donc continué à fouiller.

À la fin, il ne restait plus qu'une seule chose raisonnable à faire. Regarder les octets réels qui circulaient sur la connexion.

Jusqu'au fil

Une capture de paquets a éliminé toute ambiguïté restante. ColdFusion a envoyé ceci :

41 42 00 0e 0f 00 0a /index.cfm 00

L'octet intéressant est :

0f

AJP standard définit une collection de types de paquets utilisés pour la communication entre un serveur Web et un serveur d'applications. 0x0F ne fait pas partie des messages compris par le mod_jk standard 1.2.50, et ColdFusion l'envoyait bel et bien.

Encore plus révélateur était la charge utile :

/index.cfm

Ce n'était pas du bruit aléatoire, un paquet corrompu, ni un problème d'architecture. C'était un comportement de protocole délibéré. Le connecteur ColdFusion d'Adobe utilise une extension du protocole AJP standard. Leur version de mod_jk sait ce que signifie 0x0F. La version amont d'Apache, non.

Et c'était le mur.

Eh bien, c'est agaçant

À ce stade, l'architecture ressemblait presque à une blague.

  • ColdFusion 2025 fonctionnait sur ARM64.
  • Java 21 fonctionnait nativement sur ARM64.
  • Apache fonctionnait nativement sur ARM64.
  • J'avais compilé mod_jk nativement sur ARM64.
  • Apache pouvait se connecter à ColdFusion via AJP.
  • ColdFusion pouvait répondre via AJP.

...et tout s'est écroulé parce que l'implémentation d'Adobe parle un dialecte légèrement différent d'AJP que seul le connecteur d'Adobe comprend. Le connecteur fourni par Adobe est compilé pour x86_64.

Je suis donc parti à la recherche du code source.

Si le connecteur d'Adobe était basé sur mod_jk, peut-être que les modifications étaient disponibles quelque part dans l'installation de ColdFusion et que je pourrais simplement appliquer les modifications d'Adobe à la compilation ARM64.

Pas de chance.

L'installation contenait les binaires du connecteur et les outils wsconfig, mais je n'ai pas trouvé le code source des modifications d'Adobe. Sans savoir exactement comment Adobe avait implémenté ses extensions, je n'avais pas envie de faire de la rétro-ingénierie d'un protocole de serveur d'applications et d'assurer la maintenance de mon propre connecteur ColdFusion.

Il y a l'expérimentation, et il y a le fait de se porter volontaire pour devenir le mainteneur d'un connecteur de serveur Web Adobe ColdFusion ARM64 non officiel.

J'ai des passe-temps.

Donc, ColdFusion fonctionne-t-il sur ARM?

Oui. Et non. C'est ce qui rend le résultat intéressant.

Si la question est : "Le runtime ColdFusion 2025 peut-il s'exécuter sur Linux ARM64?" Mon expérience dit oui. J'ai exécuté ColdFusion 2025 Update 11 sur Ubuntu 24.04 ARM64 en utilisant un JVM Java 21 ARM64. Le runtime ColdFusion lui-même n'était pas ce qui a arrêté l'expérience.

Si la question est : "Puis-je prendre un déploiement ColdFusion soutenu de façon conventionnelle avec Apache et le connecteur de serveur Web d'Adobe et le migrer vers AWS Graviton?" Pas avec les composants qu'Adobe fournit actuellement. Le connecteur Apache d'Adobe est un binaire natif x86_64, et le remplacer par mod_jk ARM64 standard ne fonctionne pas parce que ColdFusion utilise des extensions propres à Adobe pour le protocole AJP.

Cette distinction compte.

Dire "ColdFusion ne fonctionne pas sur ARM" n'est pas techniquement exact. Il fonctionne. C'est l'écosystème nécessaire pour le déployer comme la plupart d'entre nous déploient réellement ColdFusion qui pose problème.

Pouviez-vous le faire fonctionner quand même?

Très certainement. Avec assez de détermination, il y a plusieurs pistes qu'une personne pourrait explorer.

  • Vous pourriez faire de la rétro-ingénierie des extensions AJP d'Adobe et corriger mod_jk en amont.
  • Vous pourriez étudier des architectures de proxy de rechange qui ne dépendent pas du connecteur Apache d'Adobe.
  • Vous pourriez exécuter des parties de la pile sous émulation x86.
  • Vous pourriez mettre ColdFusion dans un conteneur et commencer à expérimenter avec des architectures mixtes.
  • Vous pourriez probablement construire quelque chose d'assez élaboré pour qu'éventuellement un processeur ARM64 serve un fichier .cfm à Internet.

Mais ce n'était pas la question à laquelle je cherchais à répondre. Je ne cherchais pas à gagner un concours scientifique. Je cherchais à économiser de l'argent sur AWS.

Tout changement d'infrastructure doit être évalué en fonction du coût d'exploitation autant que du coût de calcul. Économiser quelques dollars sur EC2 tout en introduisant un connecteur de serveur Web non pris en charge, construit sur mesure, que je dois maintenant maintenir n'est pas une optimisation des coûts. C'est une situation de prise d'otage.

Pour l'infrastructure de production, je veux du banal. Le banal, c'est bien.

La partie que je trouve la plus intéressante

L'expérience a révélé quelque chose à propos de ColdFusion qui demeure normalement complètement invisible. La plupart des développeurs ColdFusion ne passent pas beaucoup de temps à penser au connecteur de serveur Web. Vous installez ColdFusion. Vous exécutez wsconfig. Apache ou IIS commence à envoyer des requêtes à ColdFusion. Vous poursuivez votre vie.

Mais il y a du code natif caché dans cette architecture. C'est important à mesure que le reste du monde de l'infrastructure adopte de plus en plus ARM.

Java offre un excellent soutien à ARM64. Linux offre un excellent soutien à ARM64. Apache offre un excellent soutien à ARM64. PostgreSQL, MySQL, Redis, Docker, nginx et d'énormes portions de l'écosystème moderne des serveurs fonctionnent déjà heureusement sur ARM.

AWS pousse Graviton de façon agressive parce qu'ARM peut offrir des améliorations convaincantes du rapport prix/performance.

ColdFusion est tentantement proche. L'application Java elle-même semble capable de faire le saut. Les composants d'intégration natifs autour d'elle ne l'ont pas fait.

Que devrait faire Adobe?

D'après ce que j'ai trouvé, Adobe n'aurait pas nécessairement besoin d'entreprendre un énorme portage ARM du runtime ColdFusion. Une grande partie du travail difficile a, en pratique, déjà été faite par l'écosystème Java. La pièce immédiatement manquante est beaucoup plus petite et beaucoup plus banale :

Fournir des versions ARM64 des connecteurs natifs de serveur Web.

Ou, autrement, documenter et intégrer en amont les extensions de protocole propres à ColdFusion afin que les connecteurs standards puissent interopérer avec ColdFusion.

Il peut y avoir d'autres composants ou fonctionnalités natifs de ColdFusion qui révéleraient des dépendances d'architecture lors de tests plus approfondis. Mon expérience n'était pas une suite de certification exhaustive, et le fait de démarrer ColdFusion avec succès ne prouve pas que chaque fonctionnalité de ColdFusion fonctionne correctement sur ARM64.

C'est précisément pourquoi je ne qualifierais pas cela de prêt pour la production, mais ce que j'ai trouvé est encourageant. L'obstacle fondamental n'était pas CFML. Ce n'était pas Java. Ce n'était pas Linux. Ce n'était pas Graviton.

C'était un connecteur de serveur Web.

AWS Cost Explorer avait-il raison?

Techniquement? Oui. Ce qui est irritant.

Déplacer les charges de travail appropriées vers Graviton peut vraiment réduire les coûts AWS, et la pile logicielle sous ColdFusion est de plus en plus indépendante de l'architecture. AWS a regardé mon infrastructure et a essentiellement dit : "Hé, vous pourriez dépenser moins d'argent si vous déplaciez cela vers ARM."

Et j'ai regardé ColdFusion fonctionner sur Java et j'ai pensé : "C'est en fait une assez bonne idée." Plusieurs jours plus tard, je fixais des paquets AJP hexadécimaux en essayant de comprendre ce que diable signifiait 0x0F.

Revirement: la migration vers Graviton a eu lieu quand même

Après tout cela, il y a une correction importante à apporter. La migration vers Graviton n'a pas échoué. Adobe ColdFusion sur Graviton a échoué. Ce n'est pas la même chose.

Toute l'expérience avait déjà démontré que CFML n'était pas intrinsèquement lié à x86. Java fonctionnait sur ARM. Apache fonctionnait sur ARM. ColdFusion lui-même fonctionnait sur ARM. Ce qui a finalement bloqué le déploiement Adobe était une pièce d'infrastructure native, spécifique à l'architecture, située entre Apache et ColdFusion.

Ainsi, plutôt que d'abandonner Graviton, j'ai changé la question. Si Adobe ColdFusion ne pouvait pas me donner une pile de production pratique sur ARM64, un autre moteur CFML le pouvait-il?

CommandBox change l'équation

À ce stade, j'avais prouvé quelque chose d'utile : le CFML lui-même n'était pas le problème. Alors plutôt que d'abandonner Graviton, j'ai décidé d'essayer l'application sous Ortus Solutions CommandBox.

Et après tout ce que je venais de vivre, l'expérience était presque comique.

CommandBox s'est installé sur le serveur ARM64 sans accroc. J'ai configuré le serveur CFML, je l'ai pointé vers l'application, je l'ai démarré et... Ça a fonctionné.

À peu près tout a fonctionné dès le départ. Pardonnez le jeu de mots.

Il n'y avait pas de module Apache natif à compiler. Pas de wsconfig. Aucun paquet AJP propriétaire n'apparaissant dans Wireshark. Aucun binaire mystérieux conçu pour la mauvaise architecture de processeur. L'application CFML fonctionnait simplement sur ARM64.

Apache est devenu plus simple aussi

Je voulais toujours qu'Apache soit placé devant l'application. Il faisait déjà partie de mon infrastructure, et je voulais qu'il gère le trafic HTTP et HTTPS public plutôt que d'exposer directement le serveur CommandBox.

Mais au lieu de charger un module spécifique à ColdFusion dans Apache et de communiquer avec le moteur CFML via AJP, Apache pouvait tout simplement agir comme mandataire inverse.

Conceptuellement, l'architecture est devenue :

Internet → Apache → HTTP → CommandBox → application CFML

Apache accepte la requête publique et la transmet au port local où le serveur CommandBox écoute.

C'est tout.

Aucun connecteur ColdFusion propre à l'architecture ne se trouve entre le serveur Web et le serveur d'applications. Du point de vue d'Apache, CommandBox n'est simplement qu'une autre application HTTP exécutée en amont. C'est cette distinction qui a fait disparaître tout le problème ARM.

Apache fonctionne déjà nativement sur ARM64. Java fonctionne déjà nativement sur ARM64. CommandBox m'a donné une architecture de serveur CFML qui ne dépendait pas du connecteur de serveur Web x86_64 d'Adobe. Une fois Apache configuré pour acheminer les requêtes vers CommandBox par mandataire inverse, l'application s'est comportée exactement comme je m'y attendais.

Maudit. J'aurais dû faire ça dès le départ.

La migration que je croyais difficile ne l'était pas

Je m'attendais à ce que le déplacement de l'application hors d'Adobe ColdFusion mette au jour une autre longue liste de problèmes. Ce n'est pas arrivé.

Il s'agit d'une vraie application, pas d'un test Hello World conçu spécialement pour prouver que CFML peut s'exécuter sur ARM. Il y avait amplement de possibilités pour que des différences de moteur, des dépendances Java ou des hypothèses dans l'application se manifestent.

Au lieu de cela, l'application s'est lancée et a fonctionné. C'était probablement la partie la plus surprenante de tout cet exercice.

J'avais passé un temps déraisonnable à essayer de faire passer un connecteur natif d'une architecture de processeur à une autre. Dès que j'ai cessé d'exiger ce connecteur, la migration ARM64 est devenue remarquablement ordinaire. Et une infrastructure ordinaire, c'est exactement ce que je voulais.

L'architecture qui en résulte est sans doute plus simple aussi. Apache communique en HTTP avec le serveur d'applications en utilisant le même modèle de mandataire inverse que d'innombrables autres piles applicatives. Le moteur CFML n'est pas couplé à Apache par un module natif compilé pour une architecture de processeur particulière.

Si je change un jour de nouveau l'architecture CPU sous-jacente, Apache s'en fiche. L'application s'en fiche. Java s'en fiche. Et, surtout, je n'ai pas à m'en soucier. J'adore quand je n'ai pas à m'en soucier.

Alors, la migration vers Graviton a-t-elle fonctionné ?

Absolument. L'expérience Adobe ColdFusion n'a pas produit le déploiement que j'avais initialement prévu, mais la recommandation AWS qui avait lancé toute cette aventure s'est avérée tout à fait réalisable.

L'application fonctionne sur Graviton. Elle exécute du CFML. Elle fonctionne derrière Apache. Et elle le fait sans le connecteur propre à l'architecture qui avait bloqué la version Adobe ColdFusion de l'expérience. Il y a une certaine ironie à passer des jours à déterminer précisément pourquoi quelque chose ne fonctionne pas, pour découvrir ensuite que le simple fait de changer un élément de l'architecture fait disparaître tout le problème.

Mais c'est aussi la leçon utile ici. La vraie question n'était pas de savoir si Adobe ColdFusion pouvait fonctionner sur ARM64. Nous avons prouvé que, du moins au niveau de l'exécution, c'était possible. La meilleure question était de savoir si mon application CFML pouvait fonctionner sur ARM64 dans une architecture de production que j'étais à l'aise de maintenir.

CommandBox a changé la réponse de « presque » à « oui ». Un énorme merci à Ortus Solutions. CommandBox a pris ce qui était devenu un cauchemar absurde de migration ARM et l'a rendu presque banal. L'installer, le configurer, le démarrer, et il a tout simplement fonctionné.

Alors, qu'ai-je appris ?

AWS avait raison. Java avait raison. ARM était prêt. Même ColdFusion lui-même était prêt à suivre le mouvement. J'ai simplement passé plusieurs jours à me battre avec un petit bout de code natif avant de réaliser que je n'en avais pas besoin du tout. La migration vers Graviton a réussi. L'application fonctionne heureusement sur ARM64, Apache assure heureusement le mandataire inverse vers CommandBox, et toute la pile est plus simple grâce à cela.

Est-ce que je le referais ? Absolument.

Est-ce que je commencerais par compiler mod_jk et analyser des paquets AJP ? Maudit non.

Parfois, la meilleure solution n'est pas de trouver comment faire fonctionner l'ancienne architecture. C'est de réaliser que vous n'avez plus besoin de l'ancienne architecture.